A man walks into a bar and says "I used lazy evaluation and things were 
confusing." Bartender says "You might have mixed it with I/O, but then again 
maybe you're getting tripped up by other some other not-purely-functional 
aspect of your program or the JVM, like GC or thread transitions."  

Okay, it's not as good a joke that way, but it may be more accurate.

While the OP's issue was IO-related, I've run into confusing laziness-related 
bugs, some of which were indeed Heisenbugs, that didn't have anything obvious 
to do with IO. I think some were related to GC not knowing that it could 
collect something, while others had to do with something lazy being realized in 
a different thread than I expected. For some, I've never really figured out 
what was happening, but I've nonetheless found that the problem went away when 
I switched map to mapv, or filter to filterv, etc. 

So now one of my first steps when I'm faced with a confusing bug is to stamp 
out all of the laziness except where I'm really doing things lazily on purpose, 
for a good reason. I've also come to think that the pervasiveness and 
defaultness of laziness in Clojure may not really be so wonderful after all. 
Laziness is beautiful when you want it, and when you do want it it's beautiful 
that so much of Clojure works with it so effortlessly and transparently, but it 
can also produce subtle problems when things aren't purely functional (which is 
a lot of the time, in my experience, sometimes for subtle reasons).

 -Lee


On Sep 13, 2014, at 9:32 AM, Stuart Halloway <stuart.hallo...@gmail.com> wrote:

> A man walks into a bar and says "I used lazy evaluation and things were 
> confusing." Bartender says "You mixed it with I/O" without bothering to look 
> at the code.  :-)
> 
> Your experiment uses pr-str, which uses a dynamically scoped resource *out* 
> in order to create its result.  Your observation uses println, which uses the 
> same dynamically scoped resource.  Mix in different evaluation strategies, 
> and races can lead to different outcomes. Here is a much smaller example:
> 
> (pr-str [1 2])
> (pr-str (map #(doto % println) [1 2]))
> 
> So this result is expected.  Beware I/O, and in the presence of I/O be very 
> careful in concluding that something is a value.  Your quoted-pr-str is not a 
> pure function, and so it does not make values.
> 
> Regards,
> Stu
>  

-- 
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.

Reply via email to