On Jun 12, 2009, at 7:52 PM, Wrexsoul wrote:
> Well, I did it. Made implementing lazy seqs that require stateful > generator functions easy, that is: > > (defn files-and-dirs-recursive [dir] > (super-lazy-seq [stack [(to-file dir)]] > (if-not (empty? stack) > (let [file (first stack) s (rest stack)] > (next-item > file > (if (directory? file) > (concat s (files-and-dirs file)) > s)))))) Before we order the cake, let's compare to Clojure's own implementation: (defn tree-seq "Returns a lazy sequence of the nodes in a tree, via a depth-first walk. branch? must be a fn of one arg that returns true if passed a node that can have children (but may not). children must be a fn of one arg that returns a sequence of the children. Will only be called on nodes for which branch? returns true. Root is the root node of the tree." [branch? children root] (let [walk (fn walk [node] (lazy-seq (cons node (when (branch? node) (mapcat walk (children node))))))] (walk root))) (defn file-seq "A tree seq on java.io.Files" [dir] (tree-seq (fn [#^java.io.File f] (. f (isDirectory))) (fn [#^java.io.File d] (seq (. d (listFiles)))) dir)) No macros. No magic names. No explicit state. Easier to explain. Same result. On Jun 13, 2009, at 9:37 PM, Wrexsoul wrote: > When clojure.contrib releases version 1.0, that might be an option. One of the many things I hated about other languages was the maddeningly incipient libraries. With Rails, for example, the documentation was always a blog post telling you to check out the latest version of the source from GitHub, where you would go to find it abandoned and the developed fork of someone's fork of it would have a different, undocumented API, and then you'd find out it doesn't work in your one-minor-release-old version of Rails... etc. But let's face it; we're using a language whose 1.0 release was less than two months ago. Stability is something I would expect to see in Clojure in 3-5 years, not next month. Everyone uses Contrib; it's almost an incubator for future core functionality. I can't imagine using Clojure without duck-streams. On Jun 14, 2009, at 9:58 PM, Wrexsoul wrote: > Of course, super-lazy-seq: > a) does the wrapping AND unwrapping for you > b) manages the rebinding each iteration for you, > transparently and > c) works just as well. I think the amount of debate we've seen about it here is sufficient proof that, though it works just as well, there is a certain funk to it. Personally, I don't like macros whose expansion involves magic names. What happens if you nest them—intentionally or accidentally? Also, this violates another principle of good macro writing, which is that it does not wrap a function call. Generally that means there are situations where you can't get the benefit dynamically. > The loop/recur style of super-lazy-seq use seems "closer to > functional purity" than does an explicitly stateful genfn. True, but tree-seq manages the same task with no explicit state at all. And while we can certainly embark on a debate about whether or not it is more functional to recur or to compose functions, I think we can agree that doing something with a macro that could be done with a regular function is something other than functional. If functional purity is something we are deeply concerned about. > One thing is becoming clear: in clojure, there's generally more than > one way to do it. Whatever "it" is. Agreed! And that all of the options can have their own pragmatic reasoning behind them is great, IMO. I do wonder about the interaction between garbage collection and lazily computed resources. The example code for dealing with databases in the Clojure book seemed to materialize the rows before returning them, which seems like a waste of good laziness, but it probably avoids exactly these kinds of problems. Until I run into actual issues on my own, though, I'm going to let this problem remain theoretical and hope that one of the great minds working on the core can find a solution. For some reason I believe there will probably be a good solution to this, if not generally, then at least in the 80% cases we are likely to run into. — Daniel Lyons http://www.storytotell.org -- Tell It! --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---