[swift-evolution] [Review] SE-0065 A New Model for Collections and Indices

plx plxswift at icloud.com
Wed Apr 13 18:05:09 CDT 2016


> On Apr 13, 2016, at 4:26 PM, Dave Abrahams via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
> on Tue Apr 12 2016, Brent Royal-Gordon <swift-evolution at swift.org> wrote:
> 
>> In these cases, it would be better if the `successor(of:)` method was
>> designed in a way that acknowledged and encapsulated the bounds check
>> that is usually required when it is used:
>> 
>> 	while let nextIndex = collection.successor(of: index) {
>>>> 		index = nextIndex
>> 	}
> 
> I disagree; it doesn't make sense that I should have to check for nil
> when I'm not really interested in the end of the collection as in my
> example above.  Many other nontrivial algorithms will have the same
> characteristic.  If all you need is to loop through indices to the end,
> there are lots of ways to do it.  
> 
> Looking closer, what you've got here is actually a *highly* unusual
> case, where you want a pair of indices that you want to always point to
> successive elements.  I do not know of any algorithm that would use this
> except maybe bubblesort, and frankly I cannot see any reason to change
> the standard library to support it.  Am I missing something?

Enumerating adjacent pairs from a sequence has its uses; when it’s a collection you can make the "adjacent pairs” thing itself a collection, and a pair of adjacent indices from the source collection makes a natural choice for the non-end-index indices.

In this case I agree the language doesn’t need to change; just write the generic “adjacent pairs” thingy and then use it like so:

  // if you *really* wanted values:
  for (left,right) in collection.adjacentPairs() { …

  // if you *did* actually want indices;
  for (leftIndex,rightIndex) in collection.indices.adjacentPairs() {

…but all the uses I make of it for higher-level things than e.g. “algorithms” in the STL sense.

> 
>> Given the difficulties of statically detecting index invalidation, I
>> totally agree that (as you discussed in a section I've snipped) we
>> can't statically prove indexes are safe. But we can, at the point
>> where we generate an index, easily check if that index is *currently*
>> valid. And it's something that most callers will have to do anyway if
>> we don't do it ourselves.
> 
> I really disagree with the assertion that most callers will need to do
> this.  It certainly isn't a normal thing to do in any algorithm I know
> of.  If you think I'm wrong (not unheard of!), I suggest you code up the
> method you've requested and try to apply it in actual code that
> manipulates indices, and show us how it improved the code.
> 
>>> We will change the index(_:stepsFrom:limitedBy:) overload to return
>>> an optional, and we will see what other implications it has, and how
>>> it fits into the rest of the system.
>> 
>> I'm glad to hear you'll evaluate this option, and I think it can give
>> us both what we want from this API.
>> 
>> I think having the most high-level operations incorporate bounds
>> checks, while the lower-level ones don't, is a good compromise. 
> 
> That may be the pattern you discern in Swift's bounds checks, but I just
> want to be very clear that it's not a criterion we use to make the
> determination.  I would love it if we had a more systematic way to make
> the choice to insert bounds checks or not, but for now it remains
> something of an art, trying to balance usability and performance
> concerns.
> 
>> If we encourage people to use `index(_:stepsFrom:limitedBy:)` unless
>> they know what they're doing, naïve clients will get an implicit
>> bounds check, while sophisticated, speed-sensitive clients can use
>> methods like `successor(of:)` which require them to check bounds
>> manually.
> 
> It's not a bounds check.  There are lots of ways to pass a limit that's
> outside the bounds of the collection, and you can pass a limit that's in
> the opposite direction from the offset.  If they happen to pass the
> collection's endIndex and a positive offset, it degenerates to a bounds
> check, but that's not what this method is for.
> 
> I will encourage people to use high-level algorithms where possible, so
> they're not doing index manipulations directly.  Anyone doing low-level
> index manipulations is probably implementing an algorithm, and I'll
> encourage them to do whatever will be most efficient, and then test the
> algorithm on some very strict models of Collection, that check
> everything.  You can find some of these in the StdlibUnittest library in
> the swift source tree.
> 
>> (There might even be a case for offering bounds-checked
>> `successor(of:limitedBy:)` and `predecessor(of:limitedBy:)` methods to
>> give people bounds-checked alternatives to all three.)
>> 
>>> Thanks again, Brent.
>> 
>> Thank you!
> 
> -- 
> Dave
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



More information about the swift-evolution mailing list