Safe (bounds-checked) array lookup in Swift, through optional bindings?

swift, xcode

Solution

Alex's answer has good advice and solution for the question, however, I've happened to stumble on a nicer way of implementing this functionality:

extension Collection {
    /// Returns the element at the specified index if it is within bounds, otherwise nil.
    subscript (safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

Example

let array = [1, 2, 3]

for index in -20...20 {
    if let item = array[safe: index] {
        print(item)
    }
}

Problem

If I have an array in Swift, and try to access an index that is out of bounds, there is an unsurprising runtime error: ``` var str = ["Apple", "Banana", "Coconut"] str[0] // "Apple" str[3] // EXC_BAD_INSTRUCTION ``` However, I would have thought with all the optional chaining and safety that Swift brings, it would be trivial to do something like: ``` let theIndex = 3 if let nonexistent = str[theIndex] { // Bounds check + Lookup print(nonexistent) ...do other things with nonexistent... } ``` Instead of: ``` let theIndex = 3 if (theIndex < str.count) { // Bounds check let nonexistent = str[theIndex] // Lookup print(nonexistent) ...do other things with nonexistent... } ``` But this is not the case - I have to use the ol' `if` statement to check and ensure the index is less than `str.count`. I tried adding my own `subscript()` implementation, but I'm not sure how to pass the call to the original implementation, or to access the items (index-based) without using subscript notation: ``` extension Array { subscript(var index: Int) -> AnyObject? { if index >= self.count { NSLog("Womp!") return nil } return ... // What? } } ```

Original source