To go into a bit more detail about what this code does:

Here's the code formatted idiomatically -

(defn divides? [x y] (zero? (mod x y)))

(defn prime-ub [x] (/ x (if (even? x) 2 3)))

(defn lower-primes [primes x]
  (let [ub (prime-ub x)]
    (take-while #(<= % ub) primes)))

(defn prime? [primes x]
  (println "primes" primes "x" x)
  (not-any? #(divides? x %)
            (lower-primes primes x)))

(def primes (cons 2 (lazy-seq (filter #(prime? primes %) (drop 3 
(range))))))

When the definition of primes is evaluated, the var `primes` is created, 
and the value is a cons prepending 2 to a lazy-seq. I discovered via 
experiment that running the def again does not reuse the previous value of 
primes in the definition (which makes sense I guess due to the delayed 
evaluation inside the lazy-seq).

user=> (take 20 primes)
;; truncating the output a bit this time...
(primes (2) x 3
...
primes (2) x 31
2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 primes (2 3 5 7 9 11 13 15 17 19 21 
23 25 27 29 31) x 32
primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 33
...
primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 63
31 37 41 43 47)

So I made a couple of mistakes on my first glance of what this was doing. 
It is chunking via range, but the chunk boundary is not the first 32 
elements we get from range, it is the values we get *up to 32*. This is 
because we drop 3 elements from (range), but the chunk boundary is still 
coming from (range).

I added a print for the value of "primes" within the prime? function (I 
misplaced it before above, but due to the structure of the code this did 
not affect the correctness of the output). As we see, values up to 32 see a 
set of primes being (2), and verifying, the output gives us odd numbers 
from 3 up through 31. The next 32 items are filtered properly, because as 
you can expect, every non-prime below 64 has a factor below 32.

I take back my prior assertion that the alternative to the first N elements 
seeing (2) as their list of primes is a compilation error - another 
alternative would be whole-language lazy evaluation, under which the 
definition of primes would be perfectly cromulent. Also we could hide the 
problem by eliminating chunking (getting more intuitive behavior at the 
expense of performance). Of course (iterate inc 3) avoids the problem 
because its result is not chunked.

I don't want to sound too brusque in my defense of Clojure. I'm a huge fan, 
so criticism of the language does get me a bit defensive. But preferring 
different behavior is actually reasonable here. There are other Lisps (and 
languages in the ML family) that are more internally consistent. I'll 
continue to prefer the better performance and easy access to host interop, 
even if it does violate the occasional abstraction. But of course there is 
no reason to begrudge someone else holding a different opinion, and 
choosing a language that aligns with those expectations.

But I do hope you give Clojure a chance, it's been very rewarding for me 
and I expect you'd find the same if you take the time to get to know it and 
get a feel for what's idiomatic (part of that being learning to avoid 
unintuitively odd corners of the language, which is of course not something 
you can simply figure out from first principles, it takes a bit of 
exploration and a few mistakes along the way).

On Thursday, February 12, 2015 at 9:05:24 PM UTC-8, Justin Smith wrote:
>
> it's an infinite lazy sequence with itself as a dependency. The first n 
> elements see a value of the initial non-lazy prefix. The alternative would 
> be a compilation error.

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