Fork me on GitHub

Hi there, clojure noob trying to understand the language concepts and basic structures. May I ask for some clarification? I’m trying to build a prime-number-seq generator using lazy-seq and the idea from the Sieve of Eratosthenes. This is the code I wrote:

(defn primes
     (sorted-set 2) 
     (primes (remove #(= (mod % 2) 0) (drop 2 (range))))))
   	(let [x (first s)]
      (cons x 
            (lazy-seq (primes (remove #(= (mod % x) 0) s)))

It works for getting, for example, the first 1700 primes from the sequence. When I ask for the 1772th prime number, I got a Stack Overflow. From the research I did, I suspect that this has some to do with head retention but I can’t see where is the problem. Any ideas?


I realize this is for learning purposes and hence not what you're asking, but fwiw there's a great SoE example using core.async:

Ben Hammond08:09:45

those calls to (lazy-seq (primes (remove build up and so sooner or later you blow the call stack whilst attempting to chew throrugh them

Ben Hammond08:09:50

is tangentially related


Thanks a lot @U2TCUSM2R @ben.hammond . I think that I did not got lazy-seqs the right way and I’ll do some homework on this topic before trying to move on


why are you passing s into the recursive call when you know that the first element will never be used?


In fact I’m passing it around just to capture the first element and discard all multiples of it


I'm not sure this causes your problem, but it's definitely making your code do redundant work


I think the issue is that the nested remove calls each add to the depth of the stack needed to realize the next item


by the time you get to the Nth prime you are executing (first (remove f (remove g (remove h (remove ....... coll)))))) to get x


if instead of nesting calls to remove, you pass in a set (and add an item on each recursive call) you can keep stack usage constant instead of having it grow linear with N


also, the usage of (sorted-set 2) is bizarre, because concat instantly removes all the sorted-set properties and leaves a simple lazy-seq, it would be simpler to do (cons 2 ...)


I didn’t really know about this but thanks for the clarification. I’ll try to investigate the relationship between seqs and its interactions with the collections implementations


a good rule of thumb is that anything lazy turns its result into a LazySeq - nothing lazy ever preserves the type of its input collection


(unless by coincidence the input was already lazy)


you should consider adding joker to the list - its linter mode works wonders and works for cljs:


we use it on CI to check for unused namespaces at least, and locally as an emacs mode to catch some errors early (like eslint)


I wasn't able to build joker, which was quite frustrating


whats the most idiomatic way of keeping tabs on an element of a collection? Do I store the index of the element or do I store the element and do some sort of lookups, or perhaps something else entirely?

Ben Hammond11:09:11

er, depends if your collection is a a vector or a map or a set or a list


values will always be distinct, so a set would make sense in this particular case


hmmm. That actually simplifies my use-case indeed 🙂 I could probably use the element itself and a combination of fnext and select


(let [x (calc-x)]
  (when (pred? x)
    (do-something-to x)))
I feel like this is something I could use. I like when-some, when-first, etc. Is there a more idiomatic way I should be writing this?

Ben Hammond11:09:37

(some-> x calc-x pred? do-something-to)

Ben Hammond11:09:56

not necessarily an improvement though


@ben.hammond I think that only works if pred? returns what you gave it for "true" and "nil" for false?


gives an exception about booleans & numbers 🙂


there is cond-> too, but i guess for a single condition-function pair that might be overkill

Ben Hammond11:09:37

that code you originally posted looks clear to me


@sundarj cond-> doesn't take the previous value in for the predicate though, (cond-> (calc-x) pred? do-something-to) wouldn't work


yeah you'd need a let as well alas


It's definitely clear, I've just been a little spoiled by:

(when-first [a [nil]]
  (println a))


(whenp pred? [x (calc-x)]
  (do-something-to x))
i guess you could write this macro if you fancied it 😉


I didn't think there was anything better, but I thought I'd fish in case I could rephrase it differently so there was no intermediate value.


Maybe this is just aesthetic though 🙂


no shame in that

Ben Hammond11:09:08

can any of youse point me at an explanation ?

Ben Hammond11:09:36

is it that with-bindings creates a thunk that closes over the new value, and thus handles multi-threading better?


@ben.hammond one does bindings via a {}, one does it like a let in a []

Ben Hammond11:09:06

yeah but must diff by more than just syntax


I remember reading about a book someone was writing that was a annotated read-through of the clojure.core source code. Does anyone know what I'm talking about and can point me to it?


that's it, thanks


no problem 🙂


I'm experiencing a strange issue where when I'm recompiling a test namespace (clojure.test based) after any change I get an error that all my other required namespace aliases already exist:

Caused by java.lang.IllegalStateException
   Alias sut already exists in namespace project.account-test,
   aliasing project.account
This is how the imports look:
(ns project.account-test
  (:require [project.account :as sut]
            [project.account.event-handlers :as account-events]
            [clojure.test :refer :all]))
The only way I've managed to resolve it (until the next change) is to restart the repl 😞 (ns-unmap 'project.account-test 'sut) didn't help, just as (reloaded.repl/reset-all) doesn't help. It's really annoying. Any idea what might be causing this?


@pesterhazy Thanks for the suggestion! Joker slipped by, but I'll give it a go on this code and add an entry to the post.


@vinai ns-unmap is for vars, not for aliases


@vinai to remove an alias to another ns as created by require / :as - use ns-unalias


Thank you @noisesmith, good to know. That allows me to clean up the mess manually. I still am curious why that is happening though.


if you use refresh, that deletes a namespace and replaces it


aliases aren’t by namespace name iirc, but by their object identity(?)


so my theory is that the new namespace has the same name but isn’t the one aliased


(it would require some experimentation to verify this) - regardless, the simpler solution might be to also refresh the test namespace (which does the same thing to that one as well, deleting it entirely and recreating it)


This may be more of a java question, but I've got a clojure service behind a KafkaConsumer that I've had to trim and expose as a gen-class that another service can call directly as a class/library for performance reasons, rather than going through kafka. How do I keep the quick development cycle on the clojure side without having to compile down to an uberjar and copy it into the other project (and then restart that other service) on every change? What was nice as a kafka consumer was that the service respected the reloaded workflow so a change was as simple as a (reset) in the REPL


if it makes a difference, the parent service is a scala application


the interface class is hosed, whatever you're generating with gen-class if you make a change there you're going to have to restart


but that could be just left as a tiny shim that uses tools.namespace to reload etc


@dadair if you use to look up the function to call, it will see redefinitions every time you invoke it


then you don’t need gen-class either, just use require to make clojure load your code, and Clojure.var to look up the var you can call


require won't reload files if they've changed though fyi, that's where you need tools.namespace


or, you can make sure you have a layer of indirection between the ns that uses :gen-class and the code you are calling, so that if you reload the clojure code in the process, the gen-class methods call the new definition


@bfabry it takes a :reload arg, but that’s not what I was talking about, I was talking about the usage flow when not using gen-class - you need to remember to call require before using your code


well unless you tell it to using :reload/:reload-all. but tools.namespace is a bit cleaner because it clears out old vars


the reloading part is separate, I was just describing how to replace gen-class


are there any performance considerations (on the order of ms) between using a (gen-class ..) and using


the noticible difference is on initial load (what would happen on startup in the case of gen-class, or on usage of require in the Clojure.var use case)


Noob question. How can I get (clojure.repl/source my-function) to work in a lein repl?


Just getting “source not found”


@chalcidfly by loading the definition from a file instead of typing it into the repl


the source function needs to know a file and line number, clojure doesn’t actually store the raw source of the code it compiles in memory


Using load-file?


That doesn’t seem to do anything for me


sure - that’s what cider etc. are doing


load-file ensures that the metadata is present that allows repl/source to operate


I’ve got (defn add-stuff [x] (+ x x)) in a file, I use load-file, and clojure.repl/source still says Source not found.


… checking


call meta on it to see what the var info is

dpsutton18:09:49> (meta #'permission-for)
{:arglists ([perm perms]), :line 37, :column 46, :file "*cider-repl localhost*", :name permission-for, :ns #object[clojure.lang.Namespace 0x73f10384 ""]}>> (meta #'permission-for)
{:arglists ([perm perms]), :line 44, :column 1, :file "/home/dan/ops/projects/breeze_ehr/mast/test/breeze/mast/services/accounts_test.clj", :name permission-for, :ns #object[clojure.lang.Namespace 0x73f10384 ""]}


you can't get the source code of a function that's not defined in a file


@chalcidfly oh, the other gotcha is the file needs to be in the expected place on classpath. source is an odd little macro.


Oh. what’s the default cp for lein repl?


@chalcidfly use lein cp to see it


or more accurately I guess lein with-profile repl cp (typo fixed, wants string not keyword)


I’ve got clojure-projects/expand/src on there, do I need clojure-projects/expand/src/expand as well?


no - as long as the ns-declaration in your file matches the path from src to the file


Weird. Still doesn’t work.


what if you use (require 'some.ns :reload) instead of load-file


odd that it would need that…


Thanks a million for your help, idk what was going on with load-file there


how were you invoking the load-file functionality?


@dpsutton a namespace loaded via load-file means that repl/source doesn’t work - I verified this myself


there’s only one way to use load-file, you give it a string with the path to the file


(well maybe you could also give it a object, haven’t tried, but I wouldn’t expect this to act differently either0


if you’re in a place where you you’re wishing you had multi-arity anonymous functions, is it safe to say that you’ve overcomplicated things? 🙂

Alex Miller (Clojure team)19:09:04

you can do multi-arity anonymous functions

Alex Miller (Clojure team)19:09:21

and I’d say no, not necessarily :)


I’ve missed reading that for awhile now


right under special_forms#fn. my bad!


Does anyone have advice for introducing clojure at work? I have a prototype in clojure for replacing some really gnarly xslt stuff and I’m going to be proposing switching to it to the team sometime this/next week. Curious if others have had success or failures introducing it to a non-clj workplace.


What's the rest of the stack? any jvm? Good place to focus on a similar deployment / prod environment / toolchain


It’s mostly a python shop in our area and we’re pretty functional with python. Farther towards the front-end there’s a lot of scala use. The part I’m proposing replacing is actually a Java program to run XSLT transformations and the .xsl files required to transform them, so to some degree I’m replacing one non-standard piece of tech with another one (and I think it’s fair to say that almost everyone would rather learn clj than xslt)


is there a threading operator that given a value keeps threading until a return value is not nil and then breaks early?


@beoliver that is what some-> and some->> are oops, I misread, that doesn’t exist, but you can use or


what would be threaded, since you expect things to return nil until one doesn’t


just not as pretty as (or (function-1 x) (function-2 x) ...)


that would be a straightforward macro to write, the hardest part would be a decent name for it


oh wait, is this some-fn?


@beoliver oh, yeah, this is some-fn

([p] [p1 p2] [p1 p2 p3] [p1 p2 p3 & ps])
  Takes a set of predicates and returns a function f that returns the first logical true value
  returned by one of its composing predicates against any of its arguments, else it returns
  logical false. Note that f is short-circuiting in that it will stop execution on the first
  argument that triggers a logical true result against the original predicates.


and as any return value will be truthy, this should work


=> ((some-fn :a :b :c :d) {:c 2 :d 3})


be aware that when given N args, it checks each arg separately as an arg to each fn


would it not be easier to write with reduce and reduced?


would need a let


#(reduce (fn [_ f] (some-> % (f) (reduced))) nil fns) would do it


but I think some-fn is still clearer


(apply some-fn fns) is equivalent to the above


@noisesmith I think the some-fn will work perfectly