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

Reply via email to