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 [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 unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.