[swift-evolution] Strings in Swift 4

Dave Abrahams dabrahams at apple.com
Sat Feb 11 12:06:43 CST 2017



Sent from my moss-covered three-handled family gradunza

> On Feb 11, 2017, at 5:16 AM, Karl Wagner <razielim at gmail.com> wrote:
> 
> 
>>> On 11 Feb 2017, at 04:23, Brent Royal-Gordon <brent at architechies.com> wrote:
>>> 
>>> On Feb 10, 2017, at 5:49 PM, Jonathan Hull via swift-evolution <swift-evolution at swift.org> wrote:
>>> 
>>> An easier to implement, but slightly less useful approach, would be to have methods which take an array of indexes along with the proposed change, and then it adjusts the indexes (or replaces them with nil if they are invalid) as it makes the update.  For example:
>>> 
>>>    func append(_ element:Element, adjusting: [Index]) -> [Index?]
>>>    func appending(_ element:Element, adjusting: [Index]) -> (Self, [Index?])
>> 
>> This is a very interesting idea. A couple observations:
>> 
>> 1. The problem of adjusting indices is not just a String one. It also applies to Array, among other things.

You can think of this as a generalization of AttributedString
>> 2. This logic could be encapsulated and reused in a separate type. For instance, imagine:
>> 
>>    let myStringProxy = IndexTracking(collection: myString, trackedIndices: [someIndex, otherIndex])
>>    myStringProxy.insert("foo", at: otherIndex)
>>    (someIndex, otherIndex) = (stringProxy.trackedIndices[0], stringProxy.trackedIndices[1])
>> 
>> Or, with a helper method:
>> 
>>    myString.withTracked(&someIndex) { myStringProxy in
>>        myStringProxy.insert("foo", at: otherIndex)
>>    }

You can't adjust indices in arbitrary RangeReplaceableCollections without penalizing the performance of all RangeReplaceableCollections. Also, to do it without introducing reference semantics you need to bundle the index storage with the collection or explicitly make the collection of indices to be updated avAilable input to the range replacement methods. Given the latter, you could build something like this to implement the former:

struct IndexTracked<C: RangeReplaceableCollection> 

Also, you probably want his thing to adjust ranges rather than indices because otherwise you need to decide whether to adjust an index when there is an insertion at that position.   Does it stick to the left or right element?

>> 3. An obstacle to doing this correctly is that a collection's index invalidation behavior is not expressed in the type system.

I don't see why that's an issue. 

>> If there were a protocol like:
>> 
>>    protocol RangeReplaceableWithEarlierIndexesStableCollection: RangeReplaceableCollection {}

There's one interesting wrinkle on invalidation I discovered recently: there is an important class of indices that are not invalidated as positions when they precede the change, but may be invalidated for movement: those that store some cached information about following elements, such as transcoded Unicode code units. 

>> 
>> That would help us here.
>> 
>> -- 
>> Brent Royal-Gordon
>> Architechies
>> 
> 
> 
> I mentioned this much earlier in the thread. My preferred solution would be some kind of RRC-like protocol where mutating methods returned an associated “IndexDisplacement” type. That IndexDisplacement would store, for each operation, the offset and number of index-positions which have been inserted/removed, and know how to translate an index in the previous state in to one in the new state.
> 
> You would still need to manually adjust your stored indexes using that IndexDisplacement, but it’d be less error-prone as the logic is written for you.
> 
> The standard (non-IndexDisplacement-returning) RRC methods could then be implemented as wrappers which discard the displacement.
> 
> - Karl
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170211/e02d2a37/attachment.html>


More information about the swift-evolution mailing list