[swift-evolution] Dropping Comparable requirement for indices

Brent Royal-Gordon brent at architechies.com
Wed Jul 6 07:40:13 CDT 2016

> On Jul 5, 2016, at 7:39 PM, Dave Abrahams via swift-evolution <swift-evolution at swift.org> wrote:
> Anyway, the thoughts of the community on this topic would be interesting
> to us.  We need to make a decision about this very soon.

I've wanted the Index protocols to be Comparable since the Swift 1 days. (Apple people, see rdar://17768142; non-Apple people, I was looking to measure distance and, under the old indexing model, the inability to determine which index came later was one of several impediments.) 

Going back to the beginning:

> For example, with
> Comparable indices, you can't build a linked list that supports
> restructuring (e.g. insert, delete, splice) in O(1) without invalidating
> indices... not even an unsafe linked list with reference semantics.
> [While I don't think linked lists are terribly good data structures for
> most things, they are still useful in teaching, and it bothered me that
> we were ruling them out.]  Even if you take away the index invalidation
> restriction, you have to store a counter in the index, which is an awkward inefficiency.

You *can* have O(1) restructuring without index invalidation if you're willing to tolerate O(n) comparisons; you just walk forward from the left-hand side and return `true` if you encounter the right-hand side before reaching the end. I'm not certain, but I think there's a three-way tradeoff here: you can have any two of fast restructuring, fast comparisons, and always-valid indices.

In general, though, `Collection` is not very good at modeling linked lists—for one thing, it can't model a value-typed linked list without enormous index invalidation issues. I can't quite bring myself to worry too much about linked-list handling here.

> * A Range<T>, where T is not Comparable, could be constructed with any
>  pair of Equatable T instances.  We'd only detect that the Range may be
>  invalid when T happened to also be Comparable.  However, the fact that
>  you are creating a Range already sort of implies an underlying
>  ordering.

Such a Range can't actually test whether a given value is *in* the range. That basically just makes it a glorified typealias for `(lowerBound: Bound, upperBound: Bound)`. A Range without Comparable is a type without any semantics.

> * A Collection with non-Comparable indices still imposes an ordering
>  upon the indices.

And it also still needs to be able to *test* the ordering of indices. For instance, `distance(from:to:)` is a bit difficult to implement (at least in `BidirectionalCollection`) if you can't tell which index comes earlier in the collection.

Brent Royal-Gordon

More information about the swift-evolution mailing list