Note that the problem is not that t needs to hang around; it's that t
holds a lazy sequence which hangs around in unrealized state. That
lazy sequence internally holds a thunk -- a nullary function --
capable of producing the actual sequence elements on request. It is
this thunk that holds a reference to the underlying huge sequence.
Once t is realized, the actual sequence gets cached and the thunk
becomes eligible for GC (the field holding it is set to null). If it
then needs to stay around for some other purpose, that is no problem:

user=> (let [[t d] (split-with #(< % 12) (range 1e8))] [(count t)
(count d) (count t)])
[12 99999988 12]

(Or I suppose you could return [(count d) (count t)], but (dorun t)
before that.)

Also, just to be explicit about this, calling (let [x
(produce-huge-seq)] (count x)) is not a problem, because x gets
cleared prior to control being handed off to count.

I've also discussed the details of what's going on on SO, which is
where I first noticed this question:

http://stackoverflow.com/questions/15994316/clojure-head-retention

Cheers,
Michał


On 17 April 2013 22:53, Marko Topolnik <marko.topol...@gmail.com> wrote:
> On Monday, April 15, 2013 1:50:37 AM UTC+2, tyaakow wrote:
>>
>> Thank you for your response, Marko.
>> I want to clarify one more thing:
>>
>> (let [[t d] (split-with #(< % 12) (range 1e8))]
>>     [(count d) (count t)])
>>
>>
>> does this mean that while (count d) is realizing (range 1e8) seq, it
>> becomes (also) realized within t, therefore
>> it doubles (range 1e8) in memory causing OOME while (count d) is still not
>> finished?
>
>
> There is no doubling: t and d share the same underlying lazy sequence and
> will refer to the same objects. The trouble is only that you force the
> evaluation of (count d) while (count t) still waits to be evaluated, so t
> must definitely stay bound to the head of the shared sequence.
>
>>
>> Also, you say "As count realizes one element after another, it doesn't on
>> its own retain a reference to the past elements."
>>
>> Does this mean that, eg. in repl, when I do some (count xyz) and it
>> realizes xyz, It will later need to be reevaluated (realized again) if I
>> require xyz within repl (I presume that if I require xyz later within file,
>> it wont be GC due to it and clojure will know it shouldnt be GC)
>
>
> Be careful to observe that I say "doesn't on its own retain a reference to
> the past elements". If you have xyz bound to the head of your sequence, it
> will force the entire sequence to stay in memory for as long as xyz is
> within scope (if it's a local) or indefinitely (if it's a global def'd var).
> Generally, a lazy sequence never gets un-realized once it got realized---the
> only option is for it to disappear entirely (turn into garbage).
>
> -marko
>
> --
> --
> 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/groups/opt_out.
>
>

-- 
-- 
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/groups/opt_out.


Reply via email to