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 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 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

Reply via email to