[swift-evolution] Proposal: Add Safe Subquence Access Via subscript For ColloctionType

Daniel Duan daniel at duan.org
Mon Dec 14 14:52:53 CST 2015


In CollectionType, a `Range` is accepted as the argument in a version of `subscript`, which returns a subsequence.

    [1,2,3,4][2...3] // [3, 4]

`subscript` raises a fatal error if the range is out of bound, which is really a side-effect from accessing an element with an out of bound index. This behavior forces users to check bounds beforehand. It has been serving us well.

I propose adding a new interface where user can recover from/defer out of bound error in this context. Here are two potential approaches.

Approach #1 is more conservative, we add a throwing version of `subscript`. It throws an error if the range is out of bound. We can give the range parameter a name for distinction, resulting usage would look like:

    do {
       let gimme = [1,2,3,4][safe: 2...4]
    } catch {
        recover()
    }

As an alternative, we can replace the original `subscript` with this version, breaking backward compatibilty.

Apporoach #2 is a really sweet syntax sugar. We add a new subscript that accepts 2 arugments:

    extension CollectionType where Self.Index: RandomAccessIndexType {
        public subscript(start:Int?, end:Int?) -> Self.SubSequence { ... }
    }

This version would make ANY combination of arugment safe by enabling a sematic similar to Python's slicing mechanism. Explanations come after these examples:

    [0,1,2,3][1, -1]                    // [1, 2]
    ["H","e","l","l","o"][-1000, nil]   // ["H","e","l","l","o"]
    [1,2,3,4,5,6,7,8][1,5][2,3]         // [4]

This should look familiar to Python users:

* the access is always clamped in-bound. Interpret out-of-bound number as the boundary.  [1,2,3][0: 100] means [1,2,3][0: 2].
* nil indicate the boundary itself. [1,2,3][0: nil] means [1,2,3][0: 2]
* negative index counts from the end of the sequence. [1,2,3][-2, -1] means [1,2,3][(3-2), (3-1)]

Admittedly, this syntax suger seems a little out-of-place in Swift :P

Both approaches require just a little of work. As an example, here's one implementation of the 2nd: https://github.com/dduan/Lic/blob/master/Lic/Lic.swift (please ignore the extension for String, that'd be in a separate proposal, if any).


What do you think?

- Daniel Duan


More information about the swift-evolution mailing list