Coming back to your helpful comments about relationship between acc-style and lazy...
It's worth understanding how to go back and forth between accumulator-style > and a lazy construction. You can convert the above non-lazy accumulator > version into a similar version that is lazy but has no risk of stack > overflow in the realization of that lazy flattened list: > I notice in your lazy version (below), you preface the last cons with a lazy-seq call, but do not do the same with the other cons calls (within the first recur form). I know it was only the last line that previously had a conj call and so participated in this transformation... but I'm wondering why you wouldn't also use lazy-seq with the other cons-involving line? To answer my own wondering, I am thinking it is for two reasons: 1. The main reason for using lazy-seq in the last line is to defer the recursive call to my-flatten until something wants to use it. In contrast, the other cons-involving line only conses up things which are relatively harmless to evaluate. 2. The "cons (first x) ..." will be "undone" almost immediately after the recur is executed, via the "(first xs)". So inserting laziness here is counter productive. Another question... I notice that you bound ys to (rest xs), in contrast to my choice of (next xs) in some of my implementations. I realize this is probably a minor point, but just wondering whether (rest xs) was a deliberate choice of yours, or just habit. I realize that rest maximizes laziness in contrast to next, but do we want maximum laziness here? To again attempt to answer my own question... It probably depends on what xs is being passed into my-flatten. It xs is a fully realized sequence, then (next x) would probably do. But if xs is itself lazy (and possibly expensive to compute), then using (rest x) maximizes our laziness opportunity. Maybe the thing to do would be to use (next x) here for this implementation, which is angling to be lazy... But in your earlier acc-based my-flatten, to use (next x) instead, because this implementation is eager and we know we're going to realize all of xs at some point anyway. It this logic sound? (I realize I am being pedantic, but I'm trying to understand the principles involved.) Thanks again for showing me the relationship between acc-based and lazy - helpful! > (defn my-flatten > [xs] > (if (empty? xs) () > (let [x (first xs), ys (rest xs)] > (if (sequential? x) > (if (seq x) > (recur (cons (first x) (cons (rest x) ys))) > (recur ys)) > (lazy-seq (cons x (my-flatten ys))))))) > > Basically, you just get rid of the accumulator, and in the place where you > would have conj'd in the next atomic element, you just build the lazy > sequence. > > -- 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/d/optout.