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.