On Feb 15, 2009, at 8:22 PM, Mark Engelberg wrote:
>
> My thoughts so far:
>
>
> 4. The new model is definitely more complicated to understand than
> the previous model. There was already a certain degree of mental
> overlap between collections and the seq interface. Now, there is also
> the subtle distinction between a seq and a sequence.
There will need to be good descriptions of these, but the similarity
is more in names than anything else - seqs are what they always were -
cursors, and sequences are just collections.
> rest and next
> are very similar, but one can return something empty, and one can
> return nil. Making the right choice, and interfacing with other code
> is now a bit more complicated (although people can always call seq to
> convert it into the seq/nil paradigm with certainty, which is not much
> different than before).
Code that returns sequences should use rest. next is just a
convenience function for terminal/consumer code. If you look through
the ported core code, most recurs use next, most conses inside lazy-
seqs use rest. But as you noted, if you want to ignore next, that's
fine.
> I think the additional complexity is worth it
> to solve things like the filter problem, but I think it's definitely
> more confusing than before.
>
> 5. At first glance, it seems like sticking with the original
> lazy-cons model, but removing nil punning and adding an empty sequence
> sentinel, along with your compiler enhancement, would accomplish
> everything the new "lazier" branch accomplishes with much less mental
> complexity and subtle overlap, and resulting in the most intuitive
> version of filter working as expected.
I realize you are focused on filter, but that point of the fully lazy
branch is full laziness, which would not fall out of what you
describe. lazy-cons requires the lazy sequence function do all the
work that precedes the call to lazy-cons, making functions like drop
and filter not fully lazy.
> I know you like the seq/nil
> model, and the nil punning, but since you're already moving in the
> direction of reducing reliance on this approach, I hope you've
> considered going "all the way", to see if it would solve the problem
> more elegantly. If you have considered this already, I'd be curious
> to know whether it didn't solve the problem, or whether it just
> resulted in too much breakage with existing code, or whether it's just
> a style you don't like as a matter of taste...
I'm not sure what you mean by "all the way". If you mean removing seqs
entirely, here are some issues:
(seq x) acts as a single interface to the sequence system, if it were
to return a seq[uence] collection instead of seq/nil, then all
sequence function bodies would have to return () explicitly, adding
another branch to all implementations that could otherwise use when:
(defn map [f coll]
(lazy-seq
(if (empty? coll)
()
(cons (f (first coll)) (map f (rest coll))))))
instead of:
(defn map [f coll]
(lazy-seq
(when (seq coll)
(cons (f (first coll)) (map f (rest coll))))))
But the actual definition in the lazy branch pulls the seq out of the
lazy sequence like so:
(defn map [f coll]
(lazy-seq
(when-let [s (seq coll)]
(cons (f (first s)) (map f (rest s))))))
Doing so yields a significant (> 60%) speed improvement, without it,
all lazy calls (empty?/first/rest) have a double indirection, and no
way to get rid of it.
Rich
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To post to this group, send email to [email protected]
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
-~----------~----~----~----~------~----~------~--~---