On Feb 15, 2009, at 4:44 PM, Chouser wrote:

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

While not knowing if sample code has been ported will still be an  
issue, anyone following the porting recipe:

http://clojure.org/lazier#toc7

will avoid this one as well, as the call will be to next, not rest.

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

I would just clarify that to say that the best route is *not* to  
structurally change code that uses rest, just have it call next  
instead  (unless you are writing a lazy-seq body). Using next is going  
to let you preserve your code structure and yields the simplest idioms  
- since next (still) nil puns!

core.clj e.g. is full of code that presumes it is walking a seq chain,  
and so contains lots of next calls:

http://code.google.com/p/clojure/source/diff?spec=svn1282&r=1282&format=side&path=/branches/lazy/src/clj/clojure/core.clj

There's nothing wrong with that idiom. I do not recommend that people  
leave their rest calls and 'fix' the nil puns - instead, change your  
rest calls to next, then deal with your own lazy-cons calls (possibly  
restoring some rest calls in lazy-seq bodies), then try the  
clojure.assert-if-lazy-seq flag to find any conditional use of lazy  
sequences.

Rich



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