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? } } ```