Search code examples
arraysswiftindexingswift4

Why does array indexing in Swift not return an optional value?


When accessing a dictionary, such as [String: Any], the result type is Optional(Any).

When indexing an array of [Any], the result type is Any, and the call can throw a fatal error.

Is there any reason for this difference?

It would be so nice to branch execution with a guard let, if let, ?, and ??, but instead you have to wrap array indexing in an if data.count <= index.


Solution

  • It's ultimately for performance reasons:

    Commonly Rejected Changes

    ...

    Strings, Characters, and Collection Types

    • Make Array<T> subscript access return T? or T! instead of T: The current array behavior is intentional, as it accurately reflects the fact that out-of-bounds array access is a logic error. Changing the current behavior would slow Array accesses to an unacceptable degree. This topic has come up multiple times before but is very unlikely to be accepted.

    https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md#strings-characters-and-collection-types

    Though nothing stops you from rolling your own:

    extension Collection {
        subscript(safelyIndex i: Index) -> Element? {
            get {
                guard self.indices.contains(i) else { return nil }
                return self[i]
            }
        }
    }
    
    let array = Array(0...10)
    let n = array[safelyIndex: 3]
    print(n as Any) // => Optional(3)