Thanks, Michael, for your analysis and explanation. However not even this worked:
(defn primes [] (let [primes' (atom nil)] (lazy-seq (reset! primes' (lazy-seq (cons 2 (lazy-seq (filter #(prime? (deref primes') %) (drop 3 (range)))))))))) And one thing we klnow for sure is that (deref primes') is not nil, otherwise all numbers would be output as prime numbers... Jorge. Em quinta-feira, 12 de fevereiro de 2015 18:48:10 UTC-2, Michael Blume escreveu: > > Hmm, upon further investigation I think I would not call this a bug in > Clojure that got fixed, I think I'd call this an unspecified behavior in > Clojure that happened to break your function and now happens to allow it to > work. > > Your function depends heavily on Clojure's laziness, and laziness is an > area where Clojure actually does not make a lot of strong guarantees. > > Here's an example: > > user=> (def r (into [] (range 1000))) > #'user/r > user=> (defn print-and-inc [x] (println x) (inc x)) > #'user/print-and-inc > user=> (def s (map print-and-inc r)) > #'user/s > user=> (take 1 s) > 0 > 1 > 2 > 3 > 4 > 5 > 6 > 7 > 8 > 9 > 10 > 11 > 12 > 13 > 14 > 15 > 16 > 17 > 18 > 19 > 20 > 21 > 22 > 23 > 24 > 25 > 26 > 27 > 28 > 29 > 30 > 31 > (1) > user=> > > In this example we put a thousand numbers in a vector and call the vector > r, we map print-and-inc over r and then we take one element from the > resulting lazy sequence. You might expect this to mean we print one element > from r, but in fact we print 32. This is because of an optimization detail > in Clojure's map function. It's very easy to extract "chunks" from vectors, > so in Clojure, when we map over a vector, we quickly apply the mapping > function to the first chunk of the vector and return a sequence containing > the result chunk and a promise to map over the rest. In the long run, this > speeds up map quite a bit, but in the short run, it makes map much less > lazy than one might expect. > > The upshot is that when a Clojure function promises to consume your list > lazily, you should assume that it will not, say, consume 1000 elements of > your list for no reason, or try to force its way to the end of a lazy > sequence. You should *not* assume you can know exactly when it will force > the next element, as that is essentially considered an implementation > detail. > > Returning to your code, you have > > (defn primes [] (let [primes' (atom nil)] > (reset! primes' (cons 2 (filter #(prime? @primes' %) > (drop 3 (range))))))) > > When you dereference primes, you're essentially trusting that reset! has > already run and replaced nil with your empty sequence, but in fact you > cannot be certain of that. I can see two ways to ensure your function will > work. One is sort of gratuitous defensive programming -- make your initial > value of primes' something you *wouldn't mind getting*, say > > (defn primes [] (let [primes' (atom (drop 2 (range)))] > (reset! primes' (cons 2 (filter #(prime? @primes' %) > (drop 3 (range))))))) > > The other is to wrap your whole expression in lazy-seq -- then reset! will > definitely complete before any of the logic internal to your sequence runs: > > (defn primes [] (let [primes' (atom nil)] > (lazy-seq (reset! primes' (cons 2 (filter #(prime? > @primes' %) (drop 3 (range)))))))) > > For anyone wondering, the change was Ghadi's reified range in CLJ-1515 > which I seem to recall removed/modified the chunked seq implementation from > range. > > On Thu Feb 12 2015 at 12:06:28 PM Jorge Marques Pelizzoni < > jorge.p...@gmail.com <javascript:>> wrote: > >> Well, that's a bug then :) And seems to have been fixed. Thanks! >> >> Em quinta-feira, 12 de fevereiro de 2015 17:51:13 UTC-2, Michael Blume >> escreveu: >> >>> Oh, well this is fun -- with bleeding edge clojure I get the right >>> answer, but with 1.6.0 I see the same results you did. >>> >>> >>> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clo...@googlegroups.com >> <javascript:> >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> clojure+u...@googlegroups.com <javascript:> >> For more options, visit this group at >> http://groups.google.com/group/clojure?hl=en >> --- >> You received this message because you are subscribed to the Google Groups >> "Clojure" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to clojure+u...@googlegroups.com <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.