On Wed, Dec 22, 2010 at 6:38 PM, David Nolen <dnolen.li...@gmail.com> wrote: > On Wed, Dec 22, 2010 at 6:10 PM, Ken Wesson <kwess...@gmail.com> wrote: >> >> On Wed, Dec 22, 2010 at 6:08 PM, Chris Riddoch <riddo...@gmail.com> wrote: >> > On Wed, Dec 22, 2010 at 3:46 PM, David Nolen <dnolen.li...@gmail.com> >> > wrote: >> >> A entire collection of 5e7 *objects* is being realized into memory as >> >> it is >> >> being reduced down to a single value to be stored into a var. I would >> >> expect >> >> this to perform poorly in any language. >> > >> > Range doesn't return a lazy seq? Or reduce somehow doesn't work >> > lazily? This is a little discouraging - it seems like this is a >> > perfect example of a case where laziness could significantly improve >> > things. >> >> No, both are lazy. Something else is going on here, involving def >> holding onto the head of any sequence whose expression is in the def >> form but not in a nested let or fn similar scope-creating form. >> >> http://groups.google.com/group/clojure?hl=en > > reduce is not lazy. It is eager. chouser corrected me of my misconception.
It's a consumer rather than a producer (or both) of sequences; and, as such, it's lazy inasmuch as it does not hold onto the head of the sequence, so if you pass it a lazy sequence it does not keep the whole thing realized and in memory at one time. Lazy producer -- sequence is made a bit at a time, on demand, instead of realized all at once. Lazy consumer -- sequence is traversed without retaining parts internally (holding onto the head). Map is both; range is a lazy producer; reduce is a lazy consumer but an eager producer, though not generally of a transformed version of the seq. It's possible to be a lazy consumer and an eager producer of even a transformed seq though; (doall (map f s)) presumably generates and discards an element of s for each element of output it generates, and holds onto the head of the output only, never holding more than one element of s at a time. A seq view of a collection will be an eager consumer but might be a lazy producer; (apply list a-coll) will eager-consume and eager-produce but makes a new data structure the size of the input, while a lazy seq view may only need to generate the equivalent of a single cons cell at a time, holding an element in "first" and a closure wrapping an Iterator or index of some sort in "rest" as the generator of (next the-seq-view). This reduces memory overhead somewhat, especially if traversal is never completed, compared to a seq view generator outputting (list element1 element2 element3 ...). So there's two sorts of "lazy behavior" at issue: on the producer side, does it generate a whole list or other data structure all at once, or only a bit at a time as needed? On the consumer side, does it hold onto the head of a passed-in seq or does it consume and discard one element at a time? The difficulty with clarity of language arises when something is a lazy consumer but an eager producer, like reduce, or vice versa. If you want to use lazy to generally only mean "lazy producer", that's OK, but it would be helpful to have some alternative term for a lazy consumer (that is, anything that traverses a seq without internally hanging onto the head). -- 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