Reducers [1] provide eager variants of some core seq functions (map,
filter, etc.). Note that they do not cache the result, so they recompute it
every time you use their result.

[1] http://clojure.org/reducers


On Mon, Jun 2, 2014 at 10:32 PM, Lee Spector <lspec...@hampshire.edu> wrote:

>
> I've generally liked Clojure's pervasive laziness. It's cute and it
> sometimes permits lovely, elegant approaches to particular programming
> problems. And although I've long known that it can get you into trouble in
> a few unusual cases -- I think I recall seeing a nice blog post on issues
> related to "binding" and laziness by Chas Emerick several years ago -- it
> has generally seemed safe enough for most purposes. I figured that while it
> may not always provide benefits it should at least be mostly harmless.
>
> However, after spending a couple of days tracking down a particularly
> confusing bug, and finding once again (this has happened to me at least a
> few times) that the bug was due to laziness that I never really wanted in
> the first place, I'm reconsidering.
>
> I don't have a pared-down version of the bug that I was just dealing with
> (see below for a pointer to the non-pared-down version), but it goes away
> when I wring out all of the laziness. In this particular case I do so by
> calling vec or doall on the results of all of my calls to map and other
> functions function that produce lazy sequences (none of which I actually
> want to be lazy in this application). I was getting StackOverflowErrors and
> I have a half-baked half-theory that it was due to some bad interaction
> between laziness and garbage collection, with the JVM not realizing that it
> could reclaim lazy things that weren't yet fully evaluated. That doesn't
> make complete sense to me, and maybe that kind of bad interaction is not
> even possible -- I don't know. But I do know that all is well when I wring
> out all of the laziness.
>
> One possible lesson from this experience (which was particularly
> frustrating, BTW, because the stack backtraces were particularly
> uninformative [1]) is that I should just be careful to surround any call to
> any function that produces a lazy sequence with something like vec that
> ensures that the laziness will be eliminated as soon as it is created --
> except in those relatively rare cases where I really want the laziness. But
> this would be a pain, and ugly. I rely heavily on Clojure's sequence
> processing functions and I would hate to clutter up every call to every one
> of them or to have to reimplement my own non-lazy versions of everything.
>
> Is there a more elegant way? Maybe somebody has already made non-lazy
> clones of all of the core functions that normally produce lazy sequences?
> And if so, maybe there's some clean way to cause my code to use the
> non-lazy versions unless specifically directed to use the lazy versions?
>
> I realize that this is fighting with a core feature of Clojure, and that
> the idea will probably rub lots of folks the wrong way. But I've now been
> down this road a couple of times and I'm beginning to think that I'd spend
> less time tracking down mysterious bugs if I could avoid laziness more
> easily.
>
> In case anybody is motivated to look into the specific bug that I was just
> dealing with, I've put the project at
> http://hampshire.edu/lspector/temp/world2D.zip. If you do "lein run" in
> its present state it will run fine, making little balls bounce around.
> (This is a very early version of some code that I plan to use both for
> teaching an AI class and for some ALife experiments...) But if you edit
> src/world2D/vec2D.clj, commenting out the definitions of *v, +v, and -v,
> and uncommenting the alternatives (which are the same except that they lack
> the calls to vec) then after running for a few seconds or a minute or so
> you'll get the stack overflow.
>
> Thanks for any suggestions,
>
>  -Lee
>
>
> [1] The stack traces I was getting provide no information about where/what
> the offending lazy sequences are, since they don't show locals etc. I see
> no references to any of my own code, just a repeating sequence that starts:
>
> StackOverflowError
>         clojure.core/seq (core.clj:133)
>         clojure.core/map/fn--4211 (core.clj:2490)
>         clojure.lang.LazySeq.sval (LazySeq.java:42)
>         clojure.lang.LazySeq.seq (LazySeq.java:60)
>         clojure.lang.RT.seq (RT.java:484)
>         clojure.core/seq (core.clj:133)
>         clojure.core/map/fn--4211 (core.clj:2490)
>         clojure.lang.LazySeq.sval (LazySeq.java:42)
>         clojure.lang.LazySeq.seq (LazySeq.java:60)
>         clojure.lang.RT.seq (RT.java:484)
> [etc]
>
> --
> 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.

Reply via email to