On 7/1/13 3:49 AM, Gerrard McNulty wrote:
> Suppose I had code like:
> 
> ((fn [rs] (take-last 3 rs)) (range 20000000))
> 
> This seems to run fine with no head holding.  But if I write something like:
> 
> (defn- log [f]
>   (println "start")
>   (f)
>   (println "end"))
> 
> ((fn [rs] (log #(take-last 3 rs))) (range 20000000))
> 
> Then this seems to hold on to the head.  Is there a way I can write code 
> like this where I can add functions like log without the head being held?
>

Closing over a sequence causes the head to be held. When a sequence is
passed as an argument clojure can do "locals clearing" to help avoid
holding on to head, but doesn't do so for closed over values, and doing
so for closed over values in an automated way is non-trivial.

You can tag closures you know are only going to be used once with ^:once
which will do the equivalent of locals clearing for closed over values,
but it will clear closed over values after they are used, so it is not
generally safe unless you know you are only calling the function once.
And :once may be considered an implementation detail, so I wouldn't
sprinkle it around everywhere.

If you pass a function that produces a seq instead of passing a seq it
avoids the whole mess:

((fn [rs] (log #(take-last 3 (rs)))) #(range 2000000000))

-- 
And what is good, Phaedrus,
And what is not good—
Need we ask anyone to tell us these things?

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to