Hi Evan, Thanks for the reply. I tried putting a print and it works as expected.
(let [a (atom 0) i (take-while (fn[x] (swap! a inc) (< x 100)) [1 2 3 4 5])] (println i) [@a i]) ;; <== [5 (1 2 3 4 5)] But, I still cant come up with a theory of what exactly is happening. My understanding of laziness is not deep enough, but I had ruled it out initially for 2 reasons 1) I assumed that printing out [i @a] instead of [@a i] should realize *'i'*first and @a should be correctly displayed as 5. This does not happen, it simply prints [(1 2 3 4 5) 0] if the order is reversed. 2) If I put a breakpoint in the predicate for take-while, it gets hit ( I was expecting it to not get hit if it was lazy) 3) This is the strangest observation of all: In the debugger I can see that *'a' *is getting incremented, its changing when the breakpoint is hit! but the baffling thing is, when the result is printed out, I still get 0 as the value for a. Now if a print is added, I am seeing 5 correctly printed out, but I am not satisfied with any explanation I can make up. Isn't (print i) the same as [i @a] ? since i is realized first, shouldn't @a be correctly printed? Why is the breakpoint showing me that a is changing ? What is totally strange is that '0' gets printed for @a in the end in spite of the change that I saw while debugging. I find this baffling as I was expecting the clojure runtime to have 'forgotten' about the earlier value since it is a single variable 'bound' to a single value (a --> 0) if a number gets 'put' as its value, as then it would become (a --> 5) how did it go 'back' to becoming 0 again after I saw its value changing in the debugger ? Here is the code for this behavior ( with emacs / lein / swank and a swank,core/break breakpoint) (let [a (atom 0) i (take-while (fn[x] (swap! a inc) (swank.core/break) ;; <== this shows values like : a = #<Atom@4ee2af00: 1>, a = #<Atom@4ee2af00: 2>, a = #<Atom@4ee2af00: 3> etc (< x 100)) [1 2 3 4 5])] [i @a]) ;; <== But, this prints out [(1 2 3 4 5) 0] I am reasonably sure there is no persistent data structure involved as it is an atom. By that reasoning, there should be no memory of '0'. Is there something else I am missing ? Is this normal lazy behavior ? Thanks Vinay On Tuesday, 31 July 2012 08:54:02 UTC+5:30, Evan Mezeske wrote: > > The problem is that take-while is lazy, so it does not actually perform > the "taking" operation until the lazy-seq it returns is realized, e.g. by > being printed. So when your code binds the (take-while ...) expression to > "i", the anonymous function you provided is not yet being invoked, and thus > the atom's value is not being incremented. > > Since your code dereferences the "a" atom before it forces evaluation of > the "i" lazy-seq, it gets the value 0. The "a" atom's value will only be 5 > after "i" has been fully realized, which happens later. > > So, for example, if you changed your code to this: > > (let [a (atom 0) > i (take-while (fn[x] (swap! a inc) (< x 100)) [1 2 3 4 5])] > (println i) > (println @a)) > > You will see the result you expect, because println forces "i" to be fully > realized, and thus "a" will be changed as a side-effect. > > In general, performing side-effecty operations inside lazy code is not > usually advisable, because due to the nature of laziness, the results will > not be what you'd expect if you were coming from a, say, > imperative-language background. > > Perhaps someone else can provide a link to some good reading material for > learning about laziness? > >> -- 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