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.

Reply via email to