Hi Brent,

Will an IncompleteRange always be able to be translated into the same concrete 
Range? i.e., the missing bound is just a stand in for startIndex or endIndex 
right? It seems unfortunate to have this throw away value that is only used as 
an intermediary. Especially when Collection already has an intermediary in the 
form of Index.


What if instead, you ask a collection for a prefix or suffix range from an 
index?

c.indexes(preceding: Index, inclusive: Bool)
c.indexes(succeeding: Index, inclusive: Bool)

These then return a Range or ClosedRange. This I believe would resolve the 
‘suffix’ naming issue you have highlighted here, as instead of asking for a 
suffix from the *collection*, you are asking the all successors of an *index*.


Then subscripts are also added to retrieve slices. The subscripts already infer 
the use of indexes, so there is no need to add additional words here.

c[preceding: Index, inclusive: Bool]
c[succeeding: Index, inclusive: Bool]

This is a variation of your proposed conservative index-based operation.


Also, for the removing- base operations:

c[withoutPreceding: Index, inclusive: Bool]
c[withoutSucceeding: Index, inclusive: Bool]

c.remove(preceding: Index, inclusive: Bool)
c.remove(succeeding: Index, inclusive: Bool)


I think the words ‘preceding’ and ‘succeeding’ fit in well with the concept of 
‘earliest’ and ‘latest’. Note I originally tried writing without the additional 
‘inclusive’ parameter until I realised succeeding would have to be inclusive 
for the current suffix behaviour. It appears to make the API more complicated, 
but it may help to be more explicit wrt index inclusiveness that simple prefix 
and suffix methods ignore, and also the use of indexes instead of distances (or 
perhaps iteration counts?).


Hope some of this is useful! (I might be completely missing the mark)

Patrick


> On 28 Jun 2016, at 9:46 PM, Brent Royal-Gordon via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> Addressing the same issue from several people:
> 
>> On Jun 23, 2016, at 11:28 AM, David Hart <da...@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...@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@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
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to