The documentation for Collection.index(_:offsetBy:limitedBy:)
implies it is usable for general-purpose indexing by including the following sample:
let j = numbers.index(numbers.startIndex,
offsetBy: 10,
limitedBy: numbers.endIndex)
print(j)
// Prints "nil"
This sample fails to account for offsetBy
falling on something that produces endIndex
, which requires additional checks to not crash when using it for subscripting.
Put concretely:
let streetAddress = """
1 Apple Park Way
"""
let addressLines = streetAddress.split(separator: "\n")
let index = addressLines.index(addresses.startIndex, offsetBy: 1, limitedBy: addresses.endIndex)
addressLines[index] // boom!
The doc does explain what's happening adequately: "unless that distance is beyond a given limiting index" (emphasis mine). 0 (startIndex) + 1 (offset) = 1 (endIndex)
, it's not going beyond. However, if you don't hold the endIndex
-is-the-first-past-the-end convention of Swift indexing in your head at all times, or didn't read the documentation closely, the fact alone that the method returns Index?
implies that the method will account for all possible invalid cases.
The current behavior makes sense to me, and I don't seek to change it; manual indexing is fraught, and we all understand that by now. That being said, the above code did sneak into my team's codebase because it "looked fine" during code review; or, at least, fine enough to not force a replacement with dropFirst
immediately. Overall, I'm wondering what we could be doing here better in terms of documentation or community teaching/learning.