So for Swift 3 we’re going to have the great new indexing model that performs 
index manipulation through the collection to which an index belongs.

However, it retains one of the things I didn’t like about the old model, which 
is that the distinction between forward/backward only types is a bit fuzzy, 
since the single advancedBy() method, now the index(:offsetBy:) method, was 
used for both forward and backward movement, which seems contradictory compared 
to the forward/backward only single-step methods.

Anyway, I’m wondering what people’s thoughts would be on tweaking the formula 
slightly such that there are methods that only work in a particular direction, 
i.e- we’d have three main variations of the methods like so:

    public func index(_ index:Index, advancedBy:Index.Distance) -> Index { … } 
// Available on forward and bidirectional collections
    public func index(_ index:Index, reversedBy:Index.Distance) -> Index { … } 
// Available on reverse and bidirectional collections
    public func index(_ index:Index, offsetBy:Index.Distance) -> Index { … } // 
Available only on bidirectional collections

(note, the naming isn’t definite, as reversed may not be clear enough, it’s 
just an example for now)

There are three reasons I’d prefer this:

The first is that I can pass the same distance into either of the first two 
methods, and any negation etc. is handled internally. In essence I shouldn’t 
have to handle negative distances at all when working with the first two 
methods. So if I’m working with a step size of 5, I can just pass that into the 
appropriate method, I never have to do anything with it the value itself.

The second benefit is that there should be no uncertainty about the 
capabilities of the type you’re using; if it doesn’t have the 
index(:reversedBy:) method then you can’t go backwards, same as index(before:) 
and index(after:).

The third and main benefit is that the methods are just more explicit about 
what they do, and what direction you can go in; passing negatives into either 
of the first two would produce errors outright, allowing you to pick on 
mistakes in these cases.

The other main thing is that offsetBy doesn’t indicate whether a type supports 
forward-only offsets, you have to read the documentation to determine this 
either in the method itself or the type, whereas the presence or absence of the 
first two variants are pretty clear.

Currently the offsetBy, and the previous advancedBy(), methods require 
forward-only types to produce fatal errors if handed a negative distance, and 
vice versa for backward-only types, which can only produce errors at runtime, 
whereas the presence or absence of the first two methods can be handled during 
development. You could still pass a negative value and end up with a runtime 
error instead of course, but for the types of common uses they’re intended for 
you should be unlikely to produce one.

The offsetBy form would still exist for bidirectional collections, but would 
only really be used when you need to do more complex index/distance 
manipulation outside of the type where a calculation might produce either 
positive or negative values (e.g- if you're calculating the distance and don’t 
know where two indices are in relation to each other), the rest of the time you 
should try to use the more specific, single-direction forms as they clarify 
your intent and can help to catch mistakes if you’ve incorrectly generated a 
distance for example.


Just curious what other people’s thoughts are about this?

I intended to mention this a lot sooner (to change advancedBy), but then I find 
out about the new indexing model so thought I’d wait until afterwards, then 
completely forgot =)
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to