Here's an example of what I think will be the worst kind of breakage
resulting from changing the meaning of rest from
seq-on-the-next-item-if-any-else-nil to
possibly-empty-collection-of-the-remaining-items:

(defn my-interpose [x & coll]
  (loop [v [x] coll coll]
    (if coll
      (recur (-> v (conj (first coll)) (conj x)) (rest coll))
      v)))

This is a bit like the builtin interpose, except it takes multiple
args instead of a collection, and it returns a vector with the
interposed value surrounding all the others:

(my-interpose 'x 'a 'b 'c)
-> [x a x b x c x]

At least that's what it does in svn 1282 trunk.  In 1282 lazy branch,
it's an infinite loop.  Can you spot the problem?

When discussing this yesterday in IRC, I was pretty firmly against
Rich's preferred names, for exactly this reason.  And worse than
trying to fix my own code would be the potential confusion over which
versions of examples, libs, etc. work with which versions of Clojure.

...but my position has softened, as I tried to construct an example
for this post that actually broke in a bad way.  My first several
attempts produced code that worked in both versions.

For example, my-interpose above takes multiple args so that I could
safely assume that 'coll' is a seq.  My first (unposted) version took
a collection as a second argument, but in that case a simple
"(if coll" is probably already an error, in case a user passed in an
empty vector, or some other collection.  The solution would be to test
the seq of the coll:

(defn my-interpose [x coll]
  (loop [v [x] coll coll]
    (if (seq coll)         ; Don't assume coll is a seq-or-nil
      (recur (-> v (conj (first coll)) (conj x)) (rest coll))
      v)))

That also happens to solve the lazy-branch infinite-loop problem --
what's more correct in trunk is more correct in lazy, in this case.
So I kept refining my-interpose, trying to get a version that was
correct in trunk but caused a non-exception error in lazy.  After
several iterations I finally got the one at the top of this post.

...but even that one can be caught easily by turning on
clojure.assert-if-lazy-seq, in which case you get an exception
pointing directly to the line that needs to be changed:

java.lang.Exception: LazySeq used in 'if'

So the same changes that will already have to be made to nil puns for
the other seq functions would now have to be made for uses of the new
'rest' function.

Sorry if this has been a bit long-winded, but I wanted to explain why
I've changed my mind a bit -- changing the meaning of 'rest' may not
be as bad as I had been thinking.

--Chouser

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

Reply via email to