Hi Ulrich,
Wow, you got me scratching my head because your code should not even work.
The problem I see with it is that your recursion has no base case. You have to know that 2 is prime to boot the algorithm. Eg
(def primes
(cons 2
(filter
(fn isprime[n]
(every?
#(pos? (mod n %))
(take-while #(<=(*%%)n) primes)))
(iterate inc 3))))
So now we have two behaviours to explain:
1/ why it works with iterate
2/ why it doesn't work with range
The difference comes from range returning a chunked seq (which explain the batched processing you rightly identified)
Both have a definitive reentrant smell.
1/ Let's look at the code for LazySeq
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LazySeq.java#L59 especially the seq and sval methods.
So calling seq (and thus realizing the first prime) on a yet unrealized primes sequence causes at some points to evaluate
(every?
#(pos? (mod n %))
(take-while #(<=(*%%)n) primes))
which by the nature of every? is going to realize at least one item of primes. But we are exactly trying to compute it!
From the implementation point of view, we are in the first call to seq, in the while loop. f has been cleared bu the first call to sval (which set sv) and sv cleared before entering the while and s has still its default value: null.
Thus a recursive call to seq causes is going to see sv as null and returns s which is null!
So the primes into the take-while is considered empty! Thus every? returns true and 2 is considered prime! By luck.
A sentinel or a flag could solve the problem.
2/ This is the same problem exacerbated by the fact that we are producing a chunked seq so the recursive call sees an empty prime for the first 30 items.
However if you swap iterate by range in my version (which is correct, having a base case) you still have a reentrance bug
ser=> (def primes
(cons 2
(filter
(fn isprime[n]
(every?
#(pos? (mod n %))
(take-while #(<=(* % %)n) primes)))
(drop 3 (range)))))
#'user/primes
user=> (take 50 primes)
(2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197)
Christophe