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