When a var's definition has a "lazy reference" to itself, as primes does below,
then your results will be dependent on the lazy/chunky/strict-ness of the calls
leading to the lazy reference.
The functions range, rest, and remove are chunk-aware, so the range-based
version of primes consumes a bunch of numbers before its changes become
self-visible. Other functions, such as iterate, are not chunked, so the results
are visible to primes sooner.
In most domains it is rare to have definitions with *this* kind of
self-reference. When you do have it, your best bet is to take explicit control
over the laziness by using recur and/or lazy-seq directly. The example below
(simplified from contrib) demonstrates this approach to primes:
(def primes
(concat
[2]
(let [primes-from
(fn primes-from
[n]
(if (some #(zero? (rem n %))
(take-while #(<= (* % %) n) primes))
(recur (+ n 2))
(lazy-seq (cons n (primes-from (+ n 2))))))]
(primes-from 2))))
This approach also saves memory over having a separate nums collection--nums is
fully (and unnecessarily) realized in memory in the implementations below.
Hope this helps,
Stu
> Hi,
> I tried experimenting with lazy sequences and wrote this program
>
> (def nums (cons 2 (lazy-seq (map inc nums))))
> (def primes (cons (first nums)
> (lazy-seq (->>
> (rest nums)
> (remove
> (fn [x]
> (let [dividors (take-while #(<= (* % %) x)
> primes)]
> (some #(= 0 (rem x %)) dividors))))))))
>
> It works fine. However if I redefine nums like this
> (def nums (drop 2 (range)))
>
> It gives me a wrong result
> e.g. (take 5 primes) is (2 3 5 7 9)
>
> I don't see how that can be.
> I put in a println to see where the problem is
> I inserted this line before the "some" function call.
> (println (str "x = " x ", dividors = " (seq dividors)))
> If I then define nums as (drop 2 (range))
> and write (take 5 primes) I get this output
>
> (x = 3, dividors =
> x = 4, dividors = (2)
> x = 5, dividors = (2)
> x = 6, dividors = (2)
> x = 7, dividors = (2)
> x = 8, dividors = (2)
> x = 9, dividors = (2)
> x = 10, dividors = (2)
> x = 11, dividors = (2)
> x = 12, dividors = (2)
> x = 13, dividors = (2)
> x = 14, dividors = (2)
> x = 15, dividors = (2)
> x = 16, dividors = (2)
> x = 17, dividors = (2)
> x = 18, dividors = (2)
> x = 19, dividors = (2)
> x = 20, dividors = (2)
> x = 21, dividors = (2)
> x = 22, dividors = (2)
> x = 23, dividors = (2)
> x = 24, dividors = (2)
> x = 25, dividors = (2)
> x = 26, dividors = (2)
> x = 27, dividors = (2)
> x = 28, dividors = (2)
> x = 29, dividors = (2)
> x = 30, dividors = (2)
> x = 31, dividors = (2)
> 2 3 5 7 9)
>
> That just doesn't make any sense. Can anyone explain this?
>
> btw, I use clojure 1.2.0
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to [email protected]
> Note that posts from new members are moderated - please be patient with your
> first post.
> To unsubscribe from this group, send email to
> [email protected]
> 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 post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en