On Jun 23, 4:16 am, Four of Seventeen <fsevent...@gmail.com> wrote:
> On Jun 22, 6:46 pm, "beatle...@gmail.com" <beatle...@gmail.com> wrote:
>
> > (take 10 (sort (for [x (range 1000000)] (rand)))))
>
> > Now the problem is the memory usage, as it does not merely uses memory
> > space for 10 items, but it keeps a reference to the entire sequence.
> > If I leave out the sort its all ok, and done lazily.
>
> Sort can't really be lazy without being unbelievably slow. I'm
> guessing what you want is for the long sequence produced by sort to be
> collectable garbage, aside from the ten items you take. Now the lazy
> nature of take 10 is biting you in the butt. If you make it eager with
> doall it *might* work. I'd instead do something like
>
> (vec (take 10 (sort ... )))
>
> which constructs a whole new vector of ten items and drops any
> possible reference to the input. The GC should sweep away everything
> but the ten-element vector as soon as the memory is needed elsewhere.

This is exactly what I was looking for. A way to drop the reference,
and letting the GC do its work.
Thanks!

>
> But this should not have been causing a stack overflow. If you're
> getting stack overflows, it's something else. Most likely you have
> very deep tail recursion and hoped it would be optimized like in
> Scheme. That won't work; you have to make tail recursion explicit in
> clojure using "(recur args)" instead of "(fn-name args)". You can also
> use "recur" together with "loop" to make a loop inside a function.
> It's "functional" in that, though the loop variables can be rebound
> each time around the loop, it's conceptually equivalent to defining
> and then calling a tail-recursive "letfn", and a lot less
> syntactically messy.

You're definitely right about that. Its something I already try to
take care of, by explicitly using loop / recur. (Or putting it in a
For, when possible)

> Someone here recently wrote a macro, I forget its name, to make "lazy-
> seq" similarly less messy to use. Search the site for "lazy-seq". It's
> not as useful, because usually you've got something like "take" or
> "take-while" or "map" that can be used to make the lazy sequence you
> want, and rarely need to resort to "lazy-seq" itself.
>
> But for now, you probably just need to use "recur" at your tail calls
> to fix your stack overflows, unless you have multiple functions
> calling each other with circularities. That's messier to tail-
> optimize, unfortunately.
--~--~---------~--~----~------------~-------~--~----~
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