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

Reply via email to