[swift-evolution] [Draft] Rationalizing Sequence end-operation names

Brent Royal-Gordon brent at architechies.com
Tue Jun 28 06:46:28 CDT 2016


Addressing the same issue from several people:

> On Jun 23, 2016, at 11:28 AM, David Hart <david at hartbit.com> wrote:
> 
> I’m not a fan of the subscript solutions. They both introduce new types which seems very heavyweight for such a small use case. I’d vote for keeping the current functions.

> On Jun 23, 2016, at 10:46 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
> 
> Ditto, not a fan of a subscript solution here. It is true that `suffix(from:)` seems weird at first, but it is literally nonsensical to interpret the single argument any other way, partly because of the mandatory argument label but mostly because a "suffix" that doesn't go to the end isn't a suffix.


> On Jun 23, 2016, at 1:06 PM, Anton Zhilin via swift-evolution <swift-evolution at swift.org> wrote:
> 
> -1, because [separate point snipped] they match the 
> theme you are proposing, while subscripts do not.

Superficially, `prefix(upTo:)`, `prefix(through:)` and `suffix(from:)` appear to be prefix and suffix operations, but I think that's actually a poor way to model them.

The problem is most obvious when you look at `suffix(from:)`. Imagine you have a four-element array:

	Elements:	a	b	c	d
	Indices:		[0]	[1]	[2]	[3]

`prefix(2)` and `suffix(2)` will select the first and last two elements, respectively.

	Elements:	a	b	c	d
	Indices:		[0]	[1]	[2]	[3]
	prefix(2)		^^	^^
	suffix(2)				^^	^^

And for a four-element array, so will `prefix(upTo:)` and `suffix(from:)`.

	Elements:	a	b	c	d
	Indices:		[0]	[1]	[2]	[3]
	prefix(2)		^^	^^
	  upTo: 2		^^	^^
	suffix(2)				^^	^^
	  from: 2				^^	^^

However, if you insert an element in the middle of the array, a funny thing happens:

	Elements:	a	b	c	e	d
	Indices:		[0]	[1]	[2]	[3]	[4]
	prefix(2)		^^	^^
	  upTo: 2		^^	^^
	suffix(2)					^^	^^
	  from: 2				^^	^^	^^

Unlike the other methods, adding additional elements changed the length of `suffix(from:)`'s return value. That indicates to me that it is *not* a suffix operation at all.

Now, the simplest way to resolve this is to say that `suffix(from:)` is actually misnamed; it should be `removingPrefix(upTo:)`. That will work for arrays, but not necessarily for other collections.

For instance, I've sketched a LinkedList type here: <https://gist.github.com/brentdax/20fba60dd782045faa1cfefcde298874> The important thing to note about this type is that it uses an opaque index which always points to the same node, even if you insert or remove other nodes. Thus, unlike an array, inserting or removing an element before a particular element doesn't invalidate its index. (If you're wondering, the Collection documentation doesn't seem to imply this is a forbidden design.)

Now let's build a linked list of four elements. Since this time we have non-integer indices, I'll call them i0, i1, etc.

	Elements:	a	b	c	d
	Indices:		[i0]	[i1]	[i2]	[i3]
	prefix(2)		^^	^^
	  upTo: i2		^^	^^
	suffix(2)				^^	^^
	  from: i2				^^	^^

Now what happens if we insert a new element at `j`, a new index between `i0` and `i1`?

	Elements: 	a	e	b	c	d
	Indices:		[i0]	[j]	[i1]	[i2]	[i3]
	prefix(2)		^^	^^
	  upTo: i2		^^	^^	^^
	suffix(2)					^^	^^
	  from: i2					^^	^^

How about that? We see the same anomalous expansion behavior, but from the start instead of the end of the linked list. We can, of course, expand both of them:

	Elements: 	a	e	b	c	f	d
	Indices:		[i0]	[j]	[i1]	[i2]	[k]	[i3]
	prefix(2)		^^	^^
	  upTo: i2		^^	^^	^^
	suffix(2)						^^	^^
	  from: i2					^^	^^	^^

This is not behavior you get out of *any* of the other prefix or suffix methods. What *do* you get this behavior from? Range subscripts. `linkedList[i0..<i2]` would behave in exactly the same way this does.

That's why I say in the proposal that:

> prefix(upTo:), prefix(through:), and suffix(from:) at first appear to belong to the same family as the other prefix and suffix methods, but deeper examination reveals otherwise.


These operations behave differently under mutation than the other `prefix` calls, but very similarly to other range operations. Thus, I prefer to think of them as a funny range operation, not a `prefix` or `suffix` operation.

-- 
Brent Royal-Gordon
Architechies



More information about the swift-evolution mailing list