Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a reason why array[index] doesn't return an optional?

Tags:

swift

I feel like array[index] should return an optional, given that the index could be out of bounds.

This would allow for code such as:

if let object = array[index] {   // Do stuff } 

This is easy to do with an extension method, but knowing the real reason why this is the case would be good to know.

like image 374
Christopher Kevin Howell Avatar asked Dec 17 '15 11:12

Christopher Kevin Howell


People also ask

Why must we start the array index at 0 instead of 1?

The first element of the array is exactly contained in the memory location that array refers (0 elements away), so it should be denoted as array[0] . Most programming languages have been designed this way, so indexing from 0 is pretty much inherent to the language.

What happens if you access to an array with an index out of range?

If we use an array index that is out of bounds, then the compiler will probably compile and even run. But, there is no guarantee to get the correct result. Result may unpredictable and it will start causing many problems that will be hard to find. Therefore, you must be careful while using array indexing.

Why are arrays zero indexed?

The most common answer to the array numbering question, points out that zero-based numbering comes from language design itself. In C an array points to the location in the memory, so in expression array[n], n should not be treated as an index, but as an offset from the array's head.

What is the purpose of array index?

Returns the value of an element in a table or an array, selected by the row and column number indexes. Use the array form if the first argument to INDEX is an array constant.


1 Answers

This was one of my first Swift radars, which was closed as "Behaves Correctly." It was also discussed in the dev forums. As noted by Dave Abrahams:

As to rationale, It’s easy and very common to have static knowledge that the index is in range.... In this case it’s much better to establish a precondition that the index is valid so that common use-cases don’t have to cope syntactically with a failure that can’t happen. Contrast this with dictionary indexing on keys, where it’s commonly not known whether the key is already in the dictionary.

As I've grown more experienced in Swift, I've come to agree. I do sometimes wish there were a "safe subscript" (like Mike Ash's) built-in, but I've come to agree that it shouldn't be the default.

Making it the default would make Arrays very difficult to work with, not just because of the required unwrap, but because the Index type would no longer be Int. It is required that subscript(Index) return Element (not Element?). This is why the Index of Dictionary isn't Key; it's DictionaryIndex<Key,Value>. Creating a special ArrayIndex would likely have a lot of annoying side-effects. (Maybe it would all work out in the end, but it's questionable whether it's worth it.)

The real lesson here is that you should avoid arbitrarily subscripting Arrays anyway. When practical, you should prefer to use it as a CollectionType. That means subscripting only with indexes that you fetched (with indexOf or indices for instance), and strongly favoring iteration (for-in, map) rather than subscripting. Use xs.first rather than xs[0]. If you treat it as a collection rather than an array, then you get the safety you're describing, while still leaving subscripts available when you need to solve special problems where you know the subscript is in range.

Here's an illustrative example. Consider this common loop, which you may think requires subscripting:

let xs = [1,2,3]  for i in 0..<xs.count {     print("\(i): \(xs[i])") } 

We can do this a little better and not rely on our special knowledge of array indexing and make it work for all Collections:

for i in xs.indices {     print("\(i): \(xs[i])") } 

But even that isn't necessary. We can do much better and make it work for all Sequences:

for (i, x) in xs.enumerate() {     print("\(i): \(x)") } 

No subscript required.

like image 117
Rob Napier Avatar answered Sep 21 '22 00:09

Rob Napier