On Wed, Jul 29, 2009 at 2:59 AM, Daniel Lyons <[email protected]>wrote:
> Probably it would help to try and implement a lazy > list of the Fibonacci sequence before looking at that code, and then > maybe try some other mathematical sequences that are a little easier > to construct too. > Using the super-lazy-seq macro Wrexsoul posted a month or so ago, that's dead easy: (super-lazy-seq [a 0 b 1] (next-item b b (+ a b))) On the other hand, (defn fibs [] (cons 1 (cons 1 (lazy-seq (map + (fibs) (rest (fibs))))))) (def fibs (memoize fibs)) works and is done with map rather than a looping-like construct. (Without the memoize, the latter is exponential in time; with it, though, all generated terms are retained in memory. This could be scoped, by using (binding [fibs (memoize fibs)] (take n fibs)) or whatever whenever you needed to do something with (part of) fibs, and returning something. Downside: binding doesn't work well with lazy seqs. It's actually probably easier to use the first version efficiently in a pure-functional way, even if its less pure-functional "inside". On the other hand, I'm a bit suspicious of that macro. It seems to work for common cases, but I suspect it will not work properly if you shadow one of its loop bindings with a let in the loop body, as I think it doesn't care if it's the same var so long as it has the same name when it wraps the loop vars in a deref. (map second (iterate (fn [[a b]] [b (+ a b)]) [0 1])) seems to work though and avoids the memory problems of the memoized function, the exponential tendencies of the un-memoized function, AND the super-lazy-seq macro (and even the lazy-seq macro). Interestingly, it works identically to the super-lazy-seq macro in that both start with a pair of [a = 0, b = 1] and transform it according to [a -> b, b -> (+ a b)]. In fact, there's a general correspondence between (map #(nth % n) (iterate (fn [[a b c ... z]] [exprs]) [a0 b0 c0 ... z0])) and (super-lazy-seq [a a0 b b0 c c0 ... z z0] (next-item an exprs)) and I suspect the map/iterate versions to be more efficient since they avoid atoms. (On the other hand, if the sequence is generated in a non-functional way, such as from network I/O, super-lazy-seq seems to me to be a better fit as long as you avoid shadowing any of its loop bindings internally.) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to [email protected] Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---
