Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Then all of them must be schizophrenic: forcing delay X while forcing delay X gives a stack overflow except if the delay happens to be the rest-part of a lazy seq, and then gives nil instead making the sequence seem to terminate early. That's very odd. How does it "know" whether the delay it's forcing happens to be part of a lazy seq or is instead a freestanding delay? And why should it care? Or ... could the forcing of a lazy seq element be swallowing exceptions and converting them to nil? Yet: => (take 3 (cons 1 (lazy-seq (/ 3 0 ArithmeticException Divide by zero clojure.lang.Numbers.divide (Numbers.java:156) Exceptions thrown calculating the value aren't swallowed, at least not in 1.5.1. If something is eating exceptions it's eating only StackOverflowError, or preserving and rethrowing exceptions generated by the body of the lazy-seq construct and only swallowing the ones produced by the surrounding machinery inside of the delay... Curiouser and curiouser. -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Clojure 1.6.0 user=> (def foo (delay (str @foo))) #'user/foo user=> @foo StackOverflowError clojure.lang.Delay.deref (Delay.java:37) user=> same with Clojure 1.7.0-master-SNAPSHOT, I don't see it returning nil as you said. On Fri, Feb 13, 2015 at 7:53 AM, Fluid Dynamics wrote: > On Friday, February 13, 2015 at 12:47:17 AM UTC-5, Justin Smith wrote: >> >> 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. > > > I am a fan as well. Constructive criticism is useful as it can lead to > improvements. > >> >> 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 > > > Actually, I've been using it for years. And I've never encountered behavior > like this, until now. It is definitely wrong for a lazy sequence to either > a) appear to have the wrong length or b) appear at different times to have > different lengths. As long as the var isn't rebound, "primes" indisputably > should appear to have a fixed, immutable value, whether parts of that value > are lazy via delay/force or otherwise. > > It appears that there is a buggy corner case with self-referencing delays, > where if you (delay code) and "code" has a reference to the delay and tries > to force it, it sees the delay's value as nil rather than, as it probably > should, throwing an exception. (Recursively calling the delay's code leading > to an eventual StackOverflowError seems like the only other *sensible* > alternative, but if you can detect that case and return nil instead you can > detect it and throw an exception directly. Something straightforward, like > an IAE with a message of "Delay tried to force itself on evaluation" or > something. This would be far preferable to exposing visible mutation in a > thing that is supposed to be semantically immutable, such as (rest x) > changing from nil to non-nil, and also exceptions are far preferable to > returning a logically-incorrect result without complaint.) > > Incidentally, I don't see the same behavior using my somewhat old copy of > Clojure 1.5.1: > > => (def foo (delay (str @foo))) > #'user/foo > => @foo > StackOverflowError clojure.core/deref (core.clj:2114) > > This is what I'd expect a naive implementation to do. So it looks like in > 1.6 this must have changed to produce nil from the inner @foo, for lazy > sequences to look like they terminate early from "inside themselves", and in > 1.7 it *may* have changed again. I think clarification is needed here on > what is going on. One thing already clear is the preference order of > possible behaviors: > > nil < StackOverflowError < more specific exception such as "delay tried to > force itself". > > Which suggests that 1.5.1 > 1.6, in this particular area... > > -- > 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. -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Clojure 1.5.1 user=> (def bar (cons 1 (map #(do (println %) (+ (nth bar %) %)) (range #'user/bar user=> (take 10 bar) (0 1 IndexOutOfBoundsException clojure.lang.RT.nthFrom (RT.java:795) It is possible that it is lein/REPLy that's causing the output not to be print, I've seen it done a number of times. On Fri, Feb 13, 2015 at 8:02 AM, Fluid Dynamics wrote: > And here's some really crazy behavior from 1.5.1! > > => (def bar (cons 1 (map #(do (println %) (+ #_(nth bar %) %)) (range > #'user/bar > => (take 10 bar) > (0 > > 1 > 2 > 3 > 4 > 5 > 6 > 7 > 8 > 9 > 10 > 11 > 12 > 13 > 14 > 15 > 16 > 17 > 18 > 19 > 20 > 21 > 22 > 23 > 24 > 25 > 26 > 27 > 28 > 29 > 30 > 31 > 1 0 1 2 3 4 5 6 7 8) > => (def bar (cons 1 (map #(do (println %) (+ (nth bar %) %)) (range > #'user/bar > => (take 10 bar) > IndexOutOfBoundsException clojure.lang.RT.nthFrom (RT.java:795) > > Erm, what? There should have been at least one number printed by the > (println %) before the (nth bar %) could possibly have blown up. > Furthermore, the *first* round of prints shows that % was never out of range > for an infinite lazy sequence, i.e. was never negative. So 1.5.1 is actually > behaving *schizophrenically* here: a bare delay that recursively forces > itself overflows the stack, but the delay for the next-part of a ChunkedSeq > is instead apparently being seen as holding nil when forced inside its own > evaluation. But a delay is a delay is a delay and the same behavior should > occur consistently, nil or an exception, no matter where the delay is > "located"! > > -- > 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. -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
And here's some really crazy behavior from 1.5.1! => (def bar (cons 1 (map #(do (println %) (+ #_(nth bar %) %)) (range #'user/bar => (take 10 bar) (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 1 0 1 2 3 4 5 6 7 8) => (def bar (cons 1 (map #(do (println %) (+ (nth bar %) %)) (range #'user/bar => (take 10 bar) IndexOutOfBoundsException clojure.lang.RT.nthFrom (RT.java:795) Erm, what? There should have been at least one number printed by the (println %) before the (nth bar %) could possibly have blown up. Furthermore, the *first* round of prints shows that % was never out of range for an infinite lazy sequence, i.e. was never negative. So 1.5.1 is actually behaving *schizophrenically* here: a bare delay that recursively forces itself overflows the stack, but the delay for the next-part of a ChunkedSeq is instead apparently being seen as holding nil when forced inside its own evaluation. But a delay is a delay is a delay and the same behavior should occur consistently, nil or an exception, no matter where the delay is "located"! -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
On Friday, February 13, 2015 at 12:47:17 AM UTC-5, Justin Smith wrote: > > 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. > I am a fan as well. Constructive criticism is useful as it can lead to improvements. > 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 > Actually, I've been using it for years. And I've never encountered behavior like this, until now. It is definitely wrong for a lazy sequence to either a) appear to have the wrong length or b) appear at different times to have different lengths. As long as the var isn't rebound, "primes" indisputably should appear to have a fixed, immutable value, whether parts of that value are lazy via delay/force or otherwise. It appears that there is a buggy corner case with self-referencing delays, where if you (delay code) and "code" has a reference to the delay and tries to force it, it sees the delay's value as nil rather than, as it probably should, throwing an exception. (Recursively calling the delay's code leading to an eventual StackOverflowError seems like the only other *sensible* alternative, but if you can detect that case and return nil instead you can detect it and throw an exception directly. Something straightforward, like an IAE with a message of "Delay tried to force itself on evaluation" or something. This would be far preferable to exposing visible mutation in a thing that is supposed to be semantically immutable, such as (rest x) changing from nil to non-nil, and also exceptions are far preferable to returning a logically-incorrect result without complaint.) Incidentally, I don't see the same behavior using my somewhat old copy of Clojure 1.5.1: => (def foo (delay (str @foo))) #'user/foo => @foo StackOverflowError clojure.core/deref (core.clj:2114) This is what I'd expect a naive implementation to do. So it looks like in 1.6 this must have changed to produce nil from the inner @foo, for lazy sequences to look like they terminate early from "inside themselves", and in 1.7 it *may* have changed again. I think clarification is needed here on what is going on. One thing already clear is the preference order of possible behaviors: nil < StackOverflowError < more specific exception such as "delay tried to force itself". Which suggests that 1.5.1 > 1.6, in this particular area... -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
On Friday, February 13, 2015 at 12:05:24 AM UTC-5, 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. Nope. Every component of the sequence should be a cell with a first value and a delay of the rest, or in the chunked case a cell with 32 values and a delay of the rest. The delay may or may not have already been forced. But under no circumstances should it see a sequence endpoint that never actually exists. And if something goes wrong it should be a runtime error, specifically, if computing element N requires going farther than element N-1 the computation of some delay should end up trying to force the same delay, which would hang ... at runtime. Similar to @(promise). -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
On Thursday, February 12, 2015 at 11:24:03 PM UTC-5, Justin Smith wrote: > > Not unbound primes, primes as (cons 2 ...). If you look at my post above > where I added a print statement to prime? the first 32 inputs see (2) as > the value of primes. 32 is the chunking size of the range function. That does seem broken. It certainly should not see an infinite lazy sequence as having only one element, regardless of the timing of when other elements are realized or not. -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Oh, it's much worse than anyone has mentioned yet. The whole (def primes ...) bit is also a problem. What you are saying to the compiler is "create a var named primes and assign it this lazy-seq...", and then while defining that lazy seq you are creating closures that use "primes". That sort of circular referencing is not only not recommended for code clarity reasons, but also a problem because parts of the code are delayed. What you are attempting to do is something akin to this: (def foo (fn [] (foo))) Which makes no sense at all. This is pretty much what Clojure lazy seqs are, a list who's contents are delayed via a closure. So yes, I would say most Clojure programmers are completely fine with this, as no one writes Clojure code in a self-referential way like this. Not only is it completely undefined, it's also quite hard to understand. Timothy On Thu, Feb 12, 2015 at 9:24 PM, Justin Smith wrote: > Not unbound primes, primes as (cons 2 ...). If you look at my post above > where I added a print statement to prime? the first 32 inputs see (2) as > the value of primes. 32 is the chunking size of the range function. > > -- > 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. > -- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth) -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Not unbound primes, primes as (cons 2 ...). If you look at my post above where I added a print statement to prime? the first 32 inputs see (2) as the value of primes. 32 is the chunking size of the range function. -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
I really fail to see how this can be related to chunking. So in: (def primes (cons 2 (lazy-seq (filter #(prime? primes %) (drop 3 (range)) *prime?* would be being called with unbound *primes*? And no exception would be raised and again no 4 or even numbers left to testify? Em sexta-feira, 13 de fevereiro de 2015 01:38:19 UTC-2, Justin Smith escreveu: > > Clojure is quite elegant, but it's not always unsurprising. > > Even if one surprising behavior around lazy-seq realization is changed, > others are likely to continue to occur. > > The solution to this is to not write code that implicitly relies on a > specific timing of lazy realization. If you need results to be calculated > in a certain scope, force them, and if you need results to be maximally > lazy in order to have correct code, then either force results not to chunk > (there are code examples for a "dechunk" function on the net) or refactor > to a form that doesn't rely on maximal laziness for correctness. As far as > I know, chunked sequences are not likely to leave the language any time > soon, and the behavior we see here will inevitably happen with chunked > inputs. > > > -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Clojure is quite elegant, but it's not always unsurprising. Even if one surprising behavior around lazy-seq realization is changed, others are likely to continue to occur. The solution to this is to not write code that implicitly relies on a specific timing of lazy realization. If you need results to be calculated in a certain scope, force them, and if you need results to be maximally lazy in order to have correct code, then either force results not to chunk (there are code examples for a "dechunk" function on the net) or refactor to a form that doesn't rely on maximal laziness for correctness. As far as I know, chunked sequences are not likely to leave the language any time soon, and the behavior we see here will inevitably happen with chunked inputs. On Thursday, February 12, 2015 at 7:28:13 PM UTC-8, Jorge Marques Pelizzoni wrote: > > Anyway, I would be in awe that being Closure such an expressive and > elegant language its user base is really ok with an state of affairs in > which: > > (def primes (cons 2 (lazy-seq (filter #(prime? primes %) (drop 3 > (range)) > > does not mean what it obviously should and above all means something > different from: > > (def primes (cons 2 (lazy-seq (filter #(prime? primes %) (iterate inc > 3) > > YES. I've just found out that it is (drop 3 (range)) that makes a > difference there. > > Even this will not work anymore: > > (def primes (cons 2 (for [n (drop 3 (range)) :when (prime? primes n)] n))) > > I really hope the actual developers of the language feel differently. At > least there's evidence to support that. > > Cheers, > > Jorge. > > Em sexta-feira, 13 de fevereiro de 2015 00:39:03 UTC-2, Justin Smith > escreveu: >> >> Considering for the sake of argument the possibility that it is a >> legitimate bug, and not a result of misusing the language features, it is a >> family of bug that will be more common than most, because it reflects a >> style of programming that is rare in real Clojure code. >> >> But it isn't a bug. >> >> -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Even THIS works now: (defn primes [] (let [primes' (atom nil)] (reset! primes' (cons 2 (filter #(prime? @primes' %) (iterate inc 3)) Em sexta-feira, 13 de fevereiro de 2015 01:28:13 UTC-2, Jorge Marques Pelizzoni escreveu: > > Anyway, I would be in awe that being Closure such an expressive and > elegant language its user base is really ok with an state of affairs in > which: > > (def primes (cons 2 (lazy-seq (filter #(prime? primes %) (drop 3 > (range)) > > does not mean what it obviously should and above all means something > different from: > > (def primes (cons 2 (lazy-seq (filter #(prime? primes %) (iterate inc > 3) > > YES. I've just found out that it is (drop 3 (range)) that makes a > difference there. > > Even this will not work anymore: > > (def primes (cons 2 (for [n (drop 3 (range)) :when (prime? primes n)] n))) > > I really hope the actual developers of the language feel differently. At > least there's evidence to support that. > > Cheers, > > Jorge. > > Em sexta-feira, 13 de fevereiro de 2015 00:39:03 UTC-2, Justin Smith > escreveu: >> >> Considering for the sake of argument the possibility that it is a >> legitimate bug, and not a result of misusing the language features, it is a >> family of bug that will be more common than most, because it reflects a >> style of programming that is rare in real Clojure code. >> >> But it isn't a bug. >> >> -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Anyway, I would be in awe that being Closure such an expressive and elegant language its user base is really ok with an state of affairs in which: (def primes (cons 2 (lazy-seq (filter #(prime? primes %) (drop 3 (range)) does not mean what it obviously should and above all means something different from: (def primes (cons 2 (lazy-seq (filter #(prime? primes %) (iterate inc 3) YES. I've just found out that it is (drop 3 (range)) that makes a difference there. Even this will not work anymore: (def primes (cons 2 (for [n (drop 3 (range)) :when (prime? primes n)] n))) I really hope the actual developers of the language feel differently. At least there's evidence to support that. Cheers, Jorge. Em sexta-feira, 13 de fevereiro de 2015 00:39:03 UTC-2, Justin Smith escreveu: > > Considering for the sake of argument the possibility that it is a > legitimate bug, and not a result of misusing the language features, it is a > family of bug that will be more common than most, because it reflects a > style of programming that is rare in real Clojure code. > > But it isn't a bug. > > >>> -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
no, we have not moved past this, and the error is absolutely because you take too much for granted about lazy behavior (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)] (println "primes" primes "x" x) (take-while #(<= % ub) primes))) (defn prime? [primes x] (not-any? #(divides? x %)(lower-primes primes x))) user=> (def primes (cons 2 (lazy-seq (filter #(prime? primes %) (drop 3 (range)) #'user/primes user=> (take 20 primes) (primes (2) x 3 primes (2) x 4 primes (2) x 5 primes (2) x 6 primes (2) x 7 primes (2) x 8 primes (2) x 9 primes (2) x 10 primes (2) x 11 primes (2) x 12 primes (2) x 13 primes (2) x 14 primes (2) x 15 primes (2) x 16 primes (2) x 17 primes (2) x 18 primes (2) x 19 primes (2) x 20 primes (2) x 21 primes (2) x 22 primes (2) x 23 primes (2) x 24 primes (2) x 25 primes (2) x 26 primes (2) x 27 primes (2) x 28 primes (2) x 29 primes (2) x 30 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 34 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 35 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 36 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 37 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 38 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 39 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 40 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 41 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 42 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 43 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 44 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 45 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 46 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 47 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 48 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 49 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 50 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 51 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 52 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 53 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 54 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 55 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 56 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 57 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 58 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 59 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 60 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 61 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 62 primes (2 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31) x 63 31 37 41 43 47) On Thursday, February 12, 2015 at 6:47:34 PM UTC-8, Jorge Marques Pelizzoni wrote: > > > So why isn't 4 and any even numbers in the result list? Empty primes' > allows everything to pass. We are already beyond this. I've already posted > that even this does not work: > > (def primes (cons 2 (lazy-seq (filter #(prime? primes %) (drop 3 > (range)) > > > Em sexta-feira, 13 de fevereiro de 2015 00:39:03 UTC-2, Justin Smith > escreveu: >> >> Considering for the sake of argument the possibility that it is a >> legitimate bug, and not a result of misusing the language features, it is a >> family of bug that will be more common than most, because it reflects a >> style of programming that is rare in real Clojure code. >> >> But it isn't a bug. >> >> Lazy-seqs don't promise to be "as lazy as possible", and when we step >> through the logic of the original code in Michael Blume's post, we can see >> why chunking breaks it. Taking for granted that something lazy is realized >> with a specific granularity is an error in Clojure (see also lazy-seqs used >> inside with-open blocks or db transactions - the opposite error is common, >> not being strict enough). >> >> defn primes [] (let [primes' (atom nil)] >> (reset! primes' (cons 2 (filter #(prime? @primes' %) >> (drop 3 (range))) >> >> The first time through the above code, primes' will be empty, so the >> first chunk of results will all be calculated with an empty list of >> candidate divisors. >> >>> -- 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...@googleg
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
So why isn't 4 and any even numbers in the result list? Empty primes' allows everything to pass. We are already beyond this. I've already posted that even this does not work: (def primes (cons 2 (lazy-seq (filter #(prime? primes %) (drop 3 (range)) Em sexta-feira, 13 de fevereiro de 2015 00:39:03 UTC-2, Justin Smith escreveu: > > Considering for the sake of argument the possibility that it is a > legitimate bug, and not a result of misusing the language features, it is a > family of bug that will be more common than most, because it reflects a > style of programming that is rare in real Clojure code. > > But it isn't a bug. > > Lazy-seqs don't promise to be "as lazy as possible", and when we step > through the logic of the original code in Michael Blume's post, we can see > why chunking breaks it. Taking for granted that something lazy is realized > with a specific granularity is an error in Clojure (see also lazy-seqs used > inside with-open blocks or db transactions - the opposite error is common, > not being strict enough). > > defn primes [] (let [primes' (atom nil)] > (reset! primes' (cons 2 (filter #(prime? @primes' %) > (drop 3 (range))) > > The first time through the above code, primes' will be empty, so the first > chunk of results will all be calculated with an empty list of candidate > divisors. > >> -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Considering for the sake of argument the possibility that it is a legitimate bug, and not a result of misusing the language features, it is a family of bug that will be more common than most, because it reflects a style of programming that is rare in real Clojure code. But it isn't a bug. Lazy-seqs don't promise to be "as lazy as possible", and when we step through the logic of the original code in Michael Blume's post, we can see why chunking breaks it. Taking for granted that something lazy is realized with a specific granularity is an error in Clojure (see also lazy-seqs used inside with-open blocks or db transactions - the opposite error is common, not being strict enough). defn primes [] (let [primes' (atom nil)] (reset! primes' (cons 2 (filter #(prime? @primes' %) (drop 3 (range))) The first time through the above code, primes' will be empty, so the first chunk of results will all be calculated with an empty list of candidate divisors. On Thursday, February 12, 2015 at 5:26:52 PM UTC-8, Jorge Marques Pelizzoni wrote: > > > Beautiful, Armando! Thanks for your the insight. Anyway, I really don't > buy the "that's the way it is" argument. Totally looks like a bug and I > don't find it a coincidence it is working differently in the development > branch. Thank you all for your time :) > > Em quinta-feira, 12 de fevereiro de 2015 22:30:02 UTC-2, Armando Blancas > escreveu: >> >> Jorge, I tried this on 1.6 and seemed to work: >> >> (def primes >> (cons 2 (for [n (iterate inc 3) :when (prime? primes n)] n))) >> >> >> -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Not even this works (in which I try to avoid state mutation): (def primes (cons 2 (lazy-seq (filter #(prime? primes %) (drop 3 (range)) Em quinta-feira, 12 de fevereiro de 2015 23:26:03 UTC-2, Fluid Dynamics escreveu: > > AFAICT the issue here is combining lazy evaluation with state mutation. > Don't do that. :) > -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
AFAICT the issue here is combining lazy evaluation with state mutation. Don't do that. :) -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Beautiful, Armando! Thanks for your the insight. Anyway, I really don't buy the "that's the way it is" argument. Totally looks like a bug and I don't find it a coincidence it is working differently in the development branch. Thank you all for your time :) Em quinta-feira, 12 de fevereiro de 2015 22:30:02 UTC-2, Armando Blancas escreveu: > > Jorge, I tried this on 1.6 and seemed to work: > > (def primes > (cons 2 (for [n (iterate inc 3) :when (prime? primes n)] n))) > > > -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
This is excellent, I was just working out something similar myself. The version using an atom is not idiomatic Clojure, and isn't a translation of the Haskell version either. On Thursday, February 12, 2015 at 4:30:02 PM UTC-8, Armando Blancas wrote: > > Jorge, I tried this on 1.6 and seemed to work: > > (def primes > (cons 2 (for [n (iterate inc 3) :when (prime? primes n)] n))) > > On Thursday, February 12, 2015 at 4:21:45 PM UTC-8, Jorge Marques > Pelizzoni wrote: >> >> Neither did delay help: >> >> (defn primes [] (let [primes' (atom nil)] >> (reset! primes' (delay (cons 2 (filter #(prime? (force >> (deref primes')) %) (drop 3 (range >> >> >> Serious this is not a bug? >> >> Em quinta-feira, 12 de fevereiro de 2015 22:14:46 UTC-2, Jorge Marques >> Pelizzoni escreveu: >>> >>> Thanks, Michael, for your analysis and explanation. However not even >>> this worked: >>> >>> (defn primes [] (let [primes' (atom nil)] >>> (lazy-seq (reset! primes' (lazy-seq (cons 2 (lazy-seq >>> (filter #(prime? (deref primes') %) (drop 3 (range)) >>> >>> > -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Jorge, I tried this on 1.6 and seemed to work: (def primes (cons 2 (for [n (iterate inc 3) :when (prime? primes n)] n))) On Thursday, February 12, 2015 at 4:21:45 PM UTC-8, Jorge Marques Pelizzoni wrote: > > Neither did delay help: > > (defn primes [] (let [primes' (atom nil)] > (reset! primes' (delay (cons 2 (filter #(prime? (force > (deref primes')) %) (drop 3 (range > > > Serious this is not a bug? > > Em quinta-feira, 12 de fevereiro de 2015 22:14:46 UTC-2, Jorge Marques > Pelizzoni escreveu: >> >> Thanks, Michael, for your analysis and explanation. However not even this >> worked: >> >> (defn primes [] (let [primes' (atom nil)] >> (lazy-seq (reset! primes' (lazy-seq (cons 2 (lazy-seq >> (filter #(prime? (deref primes') %) (drop 3 (range)) >> >> -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Laziness is pervasive in Haskell, for all computation (unless you force it off with special constructs). Laziness in Clojure is as pervasive as sequences, but it is not for all computation like in Haskell, and sequences have the previously-mentioned features of sometimes-more-eager-than-the-minimum required. Self-referential lazy sequences are something I would recommend actively avoiding in Clojure, unless you want to live with buggy code, or dig into the implementation and convince yourself that you are within its behavior (which can change from version to version). Andy On Thu, Feb 12, 2015 at 4:21 PM, Jorge Marques Pelizzoni < jorge.pelizz...@gmail.com> wrote: > Neither did delay help: > > (defn primes [] (let [primes' (atom nil)] > (reset! primes' (delay (cons 2 (filter #(prime? (force ( > deref primes')) %) (drop 3 (range > > > Serious this is not a bug? > > Em quinta-feira, 12 de fevereiro de 2015 22:14:46 UTC-2, Jorge Marques > Pelizzoni escreveu: >> >> Thanks, Michael, for your analysis and explanation. However not even this >> worked: >> >> (defn primes [] (let [primes' (atom nil)] >> (lazy-seq (reset! primes' (lazy-seq (cons 2 (lazy-seq >> (filter #(prime? (deref primes') %) (drop 3 (range)) >> >> -- > 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. > -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Neither did delay help: (defn primes [] (let [primes' (atom nil)] (reset! primes' (delay (cons 2 (filter #(prime? (force (deref primes')) %) (drop 3 (range Serious this is not a bug? Em quinta-feira, 12 de fevereiro de 2015 22:14:46 UTC-2, Jorge Marques Pelizzoni escreveu: > > Thanks, Michael, for your analysis and explanation. However not even this > worked: > > (defn primes [] (let [primes' (atom nil)] > (lazy-seq (reset! primes' (lazy-seq (cons 2 (lazy-seq > (filter #(prime? (deref primes') %) (drop 3 (range)) > > >>> -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Thanks, Michael, for your analysis and explanation. However not even this worked: (defn primes [] (let [primes' (atom nil)] (lazy-seq (reset! primes' (lazy-seq (cons 2 (lazy-seq (filter #(prime? (deref primes') %) (drop 3 (range)) And one thing we klnow for sure is that (deref primes') is not nil, otherwise all numbers would be output as prime numbers... Jorge. Em quinta-feira, 12 de fevereiro de 2015 18:48:10 UTC-2, Michael Blume escreveu: > > Hmm, upon further investigation I think I would not call this a bug in > Clojure that got fixed, I think I'd call this an unspecified behavior in > Clojure that happened to break your function and now happens to allow it to > work. > > Your function depends heavily on Clojure's laziness, and laziness is an > area where Clojure actually does not make a lot of strong guarantees. > > Here's an example: > > user=> (def r (into [] (range 1000))) > #'user/r > user=> (defn print-and-inc [x] (println x) (inc x)) > #'user/print-and-inc > user=> (def s (map print-and-inc r)) > #'user/s > user=> (take 1 s) > 0 > 1 > 2 > 3 > 4 > 5 > 6 > 7 > 8 > 9 > 10 > 11 > 12 > 13 > 14 > 15 > 16 > 17 > 18 > 19 > 20 > 21 > 22 > 23 > 24 > 25 > 26 > 27 > 28 > 29 > 30 > 31 > (1) > user=> > > In this example we put a thousand numbers in a vector and call the vector > r, we map print-and-inc over r and then we take one element from the > resulting lazy sequence. You might expect this to mean we print one element > from r, but in fact we print 32. This is because of an optimization detail > in Clojure's map function. It's very easy to extract "chunks" from vectors, > so in Clojure, when we map over a vector, we quickly apply the mapping > function to the first chunk of the vector and return a sequence containing > the result chunk and a promise to map over the rest. In the long run, this > speeds up map quite a bit, but in the short run, it makes map much less > lazy than one might expect. > > The upshot is that when a Clojure function promises to consume your list > lazily, you should assume that it will not, say, consume 1000 elements of > your list for no reason, or try to force its way to the end of a lazy > sequence. You should *not* assume you can know exactly when it will force > the next element, as that is essentially considered an implementation > detail. > > Returning to your code, you have > > (defn primes [] (let [primes' (atom nil)] > (reset! primes' (cons 2 (filter #(prime? @primes' %) > (drop 3 (range))) > > When you dereference primes, you're essentially trusting that reset! has > already run and replaced nil with your empty sequence, but in fact you > cannot be certain of that. I can see two ways to ensure your function will > work. One is sort of gratuitous defensive programming -- make your initial > value of primes' something you *wouldn't mind getting*, say > > (defn primes [] (let [primes' (atom (drop 2 (range)))] > (reset! primes' (cons 2 (filter #(prime? @primes' %) > (drop 3 (range))) > > The other is to wrap your whole expression in lazy-seq -- then reset! will > definitely complete before any of the logic internal to your sequence runs: > > (defn primes [] (let [primes' (atom nil)] > (lazy-seq (reset! primes' (cons 2 (filter #(prime? > @primes' %) (drop 3 (range > > For anyone wondering, the change was Ghadi's reified range in CLJ-1515 > which I seem to recall removed/modified the chunked seq implementation from > range. > > On Thu Feb 12 2015 at 12:06:28 PM Jorge Marques Pelizzoni < > jorge.p...@gmail.com > wrote: > >> Well, that's a bug then :) And seems to have been fixed. Thanks! >> >> Em quinta-feira, 12 de fevereiro de 2015 17:51:13 UTC-2, Michael Blume >> escreveu: >> >>> Oh, well this is fun -- with bleeding edge clojure I get the right >>> answer, but with 1.6.0 I see the same results you did. >>> >>> >>> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clo...@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+u...@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+u...@googlegroups.com . >> For more options, visit https://groups.google.com/d/optout. >> > -- 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...
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Hmm, upon further investigation I think I would not call this a bug in Clojure that got fixed, I think I'd call this an unspecified behavior in Clojure that happened to break your function and now happens to allow it to work. Your function depends heavily on Clojure's laziness, and laziness is an area where Clojure actually does not make a lot of strong guarantees. Here's an example: user=> (def r (into [] (range 1000))) #'user/r user=> (defn print-and-inc [x] (println x) (inc x)) #'user/print-and-inc user=> (def s (map print-and-inc r)) #'user/s user=> (take 1 s) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 (1) user=> In this example we put a thousand numbers in a vector and call the vector r, we map print-and-inc over r and then we take one element from the resulting lazy sequence. You might expect this to mean we print one element from r, but in fact we print 32. This is because of an optimization detail in Clojure's map function. It's very easy to extract "chunks" from vectors, so in Clojure, when we map over a vector, we quickly apply the mapping function to the first chunk of the vector and return a sequence containing the result chunk and a promise to map over the rest. In the long run, this speeds up map quite a bit, but in the short run, it makes map much less lazy than one might expect. The upshot is that when a Clojure function promises to consume your list lazily, you should assume that it will not, say, consume 1000 elements of your list for no reason, or try to force its way to the end of a lazy sequence. You should *not* assume you can know exactly when it will force the next element, as that is essentially considered an implementation detail. Returning to your code, you have (defn primes [] (let [primes' (atom nil)] (reset! primes' (cons 2 (filter #(prime? @primes' %) (drop 3 (range))) When you dereference primes, you're essentially trusting that reset! has already run and replaced nil with your empty sequence, but in fact you cannot be certain of that. I can see two ways to ensure your function will work. One is sort of gratuitous defensive programming -- make your initial value of primes' something you *wouldn't mind getting*, say (defn primes [] (let [primes' (atom (drop 2 (range)))] (reset! primes' (cons 2 (filter #(prime? @primes' %) (drop 3 (range))) The other is to wrap your whole expression in lazy-seq -- then reset! will definitely complete before any of the logic internal to your sequence runs: (defn primes [] (let [primes' (atom nil)] (lazy-seq (reset! primes' (cons 2 (filter #(prime? @primes' %) (drop 3 (range For anyone wondering, the change was Ghadi's reified range in CLJ-1515 which I seem to recall removed/modified the chunked seq implementation from range. On Thu Feb 12 2015 at 12:06:28 PM Jorge Marques Pelizzoni < jorge.pelizz...@gmail.com> wrote: > Well, that's a bug then :) And seems to have been fixed. Thanks! > > Em quinta-feira, 12 de fevereiro de 2015 17:51:13 UTC-2, Michael Blume > escreveu: > >> Oh, well this is fun -- with bleeding edge clojure I get the right >> answer, but with 1.6.0 I see the same results you did. >> >> >> -- > 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. > -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Or perhaps 1.7.0-alpha5 has a change vs. 1.6.0 that makes this code work by accident. Using lazy sequences to define later elements in terms of the prefix of the sequence up to that point has come up multiple times, usually with the example of generating primes (but different code each time). I don't have time to dig for those examples and the explanation right now, but I believe one potential issue is that lazy sequences are sometimes 'chunked' (the return value of range is) into groups of 32 consecutive elements, and some functions operating on sequences preserve those chunks, and operate on those batches of 32 elements all at once. Also there are some Clojure functions that are 'more eager than necessary', evaluating a few elements of the lazy sequence past the minimum needed. Andy On Thu, Feb 12, 2015 at 12:06 PM, Jorge Marques Pelizzoni < jorge.pelizz...@gmail.com> wrote: > Well, that's a bug then :) And seems to have been fixed. Thanks! > > Em quinta-feira, 12 de fevereiro de 2015 17:51:13 UTC-2, Michael Blume > escreveu: >> >> Oh, well this is fun -- with bleeding edge clojure I get the right >> answer, but with 1.6.0 I see the same results you did. >> >> >> -- > 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. > -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Well, that's a bug then :) And seems to have been fixed. Thanks! Em quinta-feira, 12 de fevereiro de 2015 17:51:13 UTC-2, Michael Blume escreveu: > > Oh, well this is fun -- with bleeding edge clojure I get the right answer, > but with 1.6.0 I see the same results you did. > > > -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Oh, well this is fun -- with bleeding edge clojure I get the right answer, but with 1.6.0 I see the same results you did. On Thu Feb 12 2015 at 11:47:54 AM Michael Blume wrote: > Strange, when I run your code I don't get 9 or 15 > > On Thu Feb 12 2015 at 11:02:00 AM Jorge Marques Pelizzoni < > jorge.pelizz...@gmail.com> wrote: > >> Hi, there! Please bear with me as I am very new to Closure (this is my >> second program ever) but have a kind of solid Haskell background. >> >> I was trying to get a version of this Haskell code: >> >> divides x y = mod x y == 0 >> primeub x = div x (if even x then 2 else 3) >> isprime primes x = all (not . divides x) (lowerprimes x) >> where >> lowerprimes x = takeWhile (<= primeub x) primes >> >> primes = 2 : filter (isprime primes) [3..] >> >> >> which works fine. E.g.: take 10 primes == [2,3,5,7,11,13,17,19,23,29]. >> In Closure, I got this: >> >> (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] (not-any? #(divides? x %)(lower-primes primes x >> ))) >> >> (defn primes [] (let [primes' (atom nil)] >> (reset! primes' (cons 2 (filter #(prime? @primes' %) >> (drop 3 (range))) >> >> However, I am getting (take 10 (primes)) == (2 3 5 7 9 11 13 15 17 19) >> (please notice the undesirable presence of 9 and 15 there...). >> >> Any ideas why this is happening? Thanks in advance. >> >> >> -- >> 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. >> > -- 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.
Re: [newbie] strange behaviour in self-referential primes lazy-seq attempt
Strange, when I run your code I don't get 9 or 15 On Thu Feb 12 2015 at 11:02:00 AM Jorge Marques Pelizzoni < jorge.pelizz...@gmail.com> wrote: > Hi, there! Please bear with me as I am very new to Closure (this is my > second program ever) but have a kind of solid Haskell background. > > I was trying to get a version of this Haskell code: > > divides x y = mod x y == 0 > primeub x = div x (if even x then 2 else 3) > isprime primes x = all (not . divides x) (lowerprimes x) > where > lowerprimes x = takeWhile (<= primeub x) primes > > primes = 2 : filter (isprime primes) [3..] > > > which works fine. E.g.: take 10 primes == [2,3,5,7,11,13,17,19,23,29]. In > Closure, I got this: > > (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] (not-any? #(divides? x %)(lower-primes primes x))) > > (defn primes [] (let [primes' (atom nil)] > (reset! primes' (cons 2 (filter #(prime? @primes' %) > (drop 3 (range))) > > However, I am getting (take 10 (primes)) == (2 3 5 7 9 11 13 15 17 19) > (please notice the undesirable presence of 9 and 15 there...). > > Any ideas why this is happening? Thanks in advance. > > > -- > 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. > -- 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.