[swift-evolution] [Review] SE-0065 A New Model for Collections and Indices
plx
plxswift at icloud.com
Tue Apr 12 23:10:37 CDT 2016
> On Apr 12, 2016, at 10:53 PM, Dmitri Gribenko <gribozavr at gmail.com> wrote:
>
> On Tue, Apr 12, 2016 at 8:46 PM, plx via swift-evolution
> <swift-evolution at swift.org> wrote:
>>
>> On Apr 12, 2016, at 6:11 PM, Haravikk <swift-evolution at haravikk.me> wrote:
>>
>> I’m a +1 for the proposal (but as I’ve implemented a bunch of collections
>> recently I’m not sure I’m looking forward to having to update my code to
>> reflect the new pattern ;)
>>
>> But I’m interested by these concerns:
>>
>> On 12 Apr 2016, at 17:57, plx via swift-evolution
>> <swift-evolution at swift.org> wrote:
>>
>> # 1: Relatively Unsafe, Pointer-Like Semantics
>> # 2: Index Invalidation Unrepresented In Type System
>>
>>
>> It seems to me as though we could solve #1 by solving #2 actually; if we
>> knew when indices were invalid, then unless we’re storing .endIndex or using
>> .startIndex or .endIndex on an empty collection (rather than .first and
>> .last) then there should no issues of the safety of these “pointers"
>> anymore.
>>
>>
>> FWIW I think “solving” invalidation in the sense of being able to detect
>> invalidity is useful, but what I’d personally be more interested in is e.g.
>> something like this:
>>
>> protocol Collection {
>>
>> // throw this into the definition:
>> static var indexCharacteristics: IndexCharacteristics { get }
>>
>> }
>>
>> extension RangeReplaceableCollection {
>>
>> mutating func removeElementsFailing(@noescape predicate: (Element) ->
>> Bool) {
>> if Self.indexCharacteristics.removalOnlyInvalidatesRightward() {
>> // presumptive “fast path”, deleting “back-to-front” to
>> // avoid making a copy. Just for sake of illustration!
>> for index in self.indices.dropLast().reverse() where
>> !predicate(self[index]) {
>> self.removeAtIndex(index)
>> }
>> } else {
>> // presumptive “slow path”, we rebuild ourself with the failing
>> elements omitted
>> self = Self(self.lazy.filter() { predicate($0) })
>> // ^ assuming self-assignment allowed...
>> }
>> }
>>
>> }
>
> Hi plx,
>
> In case of RangeReplaceableCollection, the index invalidation rules
> that we currently have in mind (but haven't documented in public
> documentation yet) imply that your fast path is always correct.
That’s good news!
Fact is, I only went with that because I was actually fishing around for the weakest generic collection protocol that supported removal, and that seems to be it.
It’d be a more compelling motivating example if it used, e.g.:
// “fictional”, not in stdlib:
protocol IndexDeletingCollection : Collection {
mutating func removeAtIndex(i: Index) -> Generator.Element
}
…since there’d then be a more realistic chance of having multiple “flavors” of invalidation to consider.
But I could certainly live with a setup wherein generally protocols typically required “compatible” invalidation semantics on their indices.
>
> Dmitri
>
> --
> main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
> (j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr at gmail.com>*/
More information about the swift-evolution
mailing list