On Mon, Dec 6, 2010 at 7:10 PM, Michael Gardner <gardne...@gmail.com> wrote:
> On Dec 6, 2010, at 5:35 PM, Ken Wesson wrote:
>
>> Who was relying on the order? If you merely relied on seeing 5 or 6,
>> or on not seeing 3 or 4 twice, you were screwed.
>
> Ah, I misunderstood what you wrote. Obviously (seq) should hand you each item 
> in the collection exactly once, but that's at a weaker guarantee than that 
> different calls to (seq) on the same collection should always hand them to 
> you in the same order.
>
>> The point was that you can't even rely on seeing all of the elements,
>> once each, in *some* order, unless the seq is a copy instead of a view
>> backed by the other data structure.
>
> I don't see how this follows. It seems like you're making some unstated 
> assumptions about how (seq) gets items from the underlying collection.

I'll try this one more time. You suggested the innards, and with them
the seq order of the elements, might get rearranged. If (seq c)
produces a lazy seq that is backed by some kind of iterator traversing
some data structure underlying c and such a rearrangement happens
during said traversal, then there are two branching possibilities.

1. The iterator just keeps traversing even though it's now on
quicksand. (Or worse, it stops with a ConcurrentModificationException
or something.) In that event, the seq contract is broken. At best
you'll get traversals like (1 3 4 2 4 3) sometimes from traversing
things like #{1 2 3 4 5 6}; more likely you'll get things like (1 3 4
2) that simply stop short and omit items; at worst, exception throws.

2. There is some way in which the seq "holds onto" a particular
ordering of the elements, even through rearrangements. The seq may be
non-lazy, created as a PersistentList of the elements when seq was
called; or the structure may include a (stable!) linking system for
traversing the elements (ala java.util.LinkedHashMap), or something.

In case #2, seq meets its contract, but nth can also be made to work
easily enough; in the linking-system case nth "naturally" works
stably, whereas in the non-lazy case the seq version once created can
be cached, both making repeated calls to seq cheaper and making nth
work in a consistent way on that instance.

In case #1, on the other hand, though nth can't be made to work *seq
can't be made to work either* even though it is supported -- it's
supported, and yet *it'll break and needs to be fixed* if the
structure is rewritten to rearrange its innards. And fixing it will
necessarily also fix nth.

>> And if it's a copy, it is
>> expensive to produce. And if it is expensive to produce, it can be
>> cached once produced. And if it can be cached once produced, nth can
>> give consistent results by consulting the cached seq.
>
> It's not just about (nth) giving consistent results. It's also about forcing 
> the programmer to make his intentions explicit, per Rich's quote.

We may just have to agree to disagree about that. It seems to me that
calling nth, or first, or seq, or anything like that makes the
programmer's intentions explicit, as those are all clearly treating
the structure as a sequence. It's calling (foo coll) where foo calls
(nth (seq coll)) or somesuch under the hood that doesn't make the
programmer's intentions (as) explicit; they're calling some function
on, say, a map and it may not be especially obvious that that function
treats the map (and anything else passed to it) as a sequence.

Anyway, you can't legislate code clarity at the language level. They
tried that with Java and look where it got them. Annotations,
generics, and checked exceptions, oh my!

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

Reply via email to