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