When you work with a lazy sequence, Clojure (java really)
automatically garbage-collects elements you're done with. It can only
be certain you're done with them if you no longer have any reference
to them, direct or indirect. If you've bound the head of the sequence
to a local, then you can still access every element of the lazy
sequence, so none can be garbage collected. If instead you pass the
element through a set of operations without ever binding it to
anything, each element can be GCed immediately after you're done
processing it (though in practice they won't be until space is
needed).

Observe the difference:

user=> (nth (map #(make-array Double/TYPE (* % 10000))
                 (range))
            100)
#<double[] [...@781046>

user=> (let [x (map #(make-array Double/TYPE (* % 10000))
                    (range))]
         (nth x 100))
java.lang.OutOfMemoryError: Java heap space (NO_SOURCE_FILE:0)


You will probably need different numbers to reproduce these results on
your system depending on how much heap space you let clojure have, but
that's the idea.

And you make a good point about binding sequences to locals in a let.
I'm not sure, but I think you're right: if the sequences are large
enough the let-version will fail while the ->> (or nested-forms)
version will succeed.

On Oct 20, 10:34 am, cej38 <junkerme...@gmail.com> wrote:
> This question leads into something that I read in Joy of Clojure (page
> 161 in the latest MEAP edition):
> "If you manage to hold onto the head of a sequence somewhere within a
> function, then that sequence will be prevented from being garbage
> collected. The simplest way to retain the head of sequence is to bind
> it to a local. This condition can occur with any type of value bind be
> it to a reference type or through the usage of let or binding."
>
> I am not sure what this means, but I think it would mean that using
> let as you do, could cause garbage collection problems.  Thus, it
> might be better to follow the advice of Stuart and Luc.
>
> Chad
>
> PS. Clarification of the statement from the Joy of Clojure would be
> helpful.
>
> On Oct 19, 11:19 pm, Dave Ray <dave...@gmail.com> wrote:
>
> > Hey,
>
> > I'm parsing a file with a chain of filter and map operations. To make
> > it a little more readable (to me), I put the steps in a let like this:
>
> > (defn parse-dictionary
> >   [reader]
> >   (let [lines    (read-lines reader)
> >         trimmed  (map #(.trim %1) lines)
> >         filtered (filter is-dictionary-entry? trimmed)]
> >      (map parse-entry filtered)))
>
> > Is this style of let considered good/bad stylistically? Are there
> > technical tradeoffs between this and a bunch of nested forms?
>
> > Thanks!
>
> > Dave
>
>

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