Arrays Returning Optionals instead of Index Out of Bounds

(First time using a mailing list; I hope this message ends up in the correct thread)

This is a topic that comes up regularly on the Swift evolution mailing list and off it.
After reading through all the respective threads again, there seem to be the following two camps:

Arguments made for crashing when accessing a non-existent index:
- fast
- shows bugs quickly

Arguments made in favor of returning an optional by default:
- safe (as in "doesn't crash")
- similar to what other modern languages do
- what an unexperienced Swift developer would expect

All are valid arguments, but for different use cases.
In my opinion, the biggest problem is that there's no indication that subscripting can crash on the default array. Alternative subscripts for bounded access wouldn't solve this either.

Maybe Swift should have two different array classes: A fast, fast-failing "UnsafeArray" and a default safe "Array". This would prevent unexpected crashes for new Swift programmers while still providing a faster alternative for those who do low-level stuff. The name "UnsafeArray" would clearly communicate that this class should be handled with care.

- Andreas

(First time using a mailing list; I hope this message ends up in the
correct thread)

This is a topic that comes up regularly on the Swift evolution mailing
list and off it.
After reading through all the respective threads again, there seem to be
the following two camps:

Arguments made for crashing when accessing a non-existent index:
- fast
- shows bugs quickly

Arguments made in favor of returning an optional by default:
- safe (as in "doesn't crash")
- similar to what other modern languages do
- what an unexperienced Swift developer would expect

All are valid arguments, but for different use cases.
In my opinion, the biggest problem is that there's no indication that
subscripting can crash on the default array. Alternative subscripts for
bounded access wouldn't solve this either.

Maybe Swift should have two different array classes: A fast, fast-failing
"UnsafeArray" and a default safe "Array". This would prevent unexpected
crashes for new Swift programmers while still providing a faster
alternative for those who do low-level stuff. The name "UnsafeArray" would
clearly communicate that this class should be handled with care.

I can see where you're coming from, but IMO the ship has sailed to change
the performance characteristics of every array currently written in Swift.
Moreover, as Dave A. has pointed out before, crashing isn't "unsafe" in the
sense it's used in Swift. It's actually quite safe, in that you're
immediately prevented from doing anything nonsensical based on your
incorrect assumption. If I saw a type called UnsafeArray, I'd imagine that
it'd allow me to peek beyond the end of my array without crashing.

···

On Thu, Jun 23, 2016 at 5:12 AM, Andreas Ley via swift-evolution < swift-evolution@swift.org> wrote:

- Andreas
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Please find the related proposal which was formed after the long discussion in the list:

Here is the pull request on the swift-evolution repo:

···

On 23.06.2016 13:12, Andreas Ley via swift-evolution wrote:

(First time using a mailing list; I hope this message ends up in the correct thread)

This is a topic that comes up regularly on the Swift evolution mailing list and off it.
After reading through all the respective threads again, there seem to be the following two camps:

Arguments made for crashing when accessing a non-existent index:
- fast
- shows bugs quickly

Arguments made in favor of returning an optional by default:
- safe (as in "doesn't crash")
- similar to what other modern languages do
- what an unexperienced Swift developer would expect

All are valid arguments, but for different use cases.
In my opinion, the biggest problem is that there's no indication that subscripting can crash on the default array. Alternative subscripts for bounded access wouldn't solve this either.

Maybe Swift should have two different array classes: A fast, fast-failing "UnsafeArray" and a default safe "Array". This would prevent unexpected crashes for new Swift programmers while still providing a faster alternative for those who do low-level stuff. The name "UnsafeArray" would clearly communicate that this class should be handled with care.

- Andreas
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I still think the best solution is that proposal, plus allowing subscript setters to take a T if their getters return a T? or T!, to avoid the problem of `nil` becoming the wrong type in cases where T itself is NilLiteralConvertible.

- Dave Sweeris

···

On Jun 23, 2016, at 7:34 AM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

Please find the related proposal which was formed after the long discussion in the list:

https://github.com/luish/swift-evolution/blob/proposal-lenient-collection-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

Here is the pull request on the swift-evolution repo:
Proposal: more lenient subscript methods over Collections by luish · Pull Request #328 · apple/swift-evolution · GitHub

On 23.06.2016 13:12, Andreas Ley via swift-evolution wrote:

(First time using a mailing list; I hope this message ends up in the correct thread)

This is a topic that comes up regularly on the Swift evolution mailing list and off it.
After reading through all the respective threads again, there seem to be the following two camps:

Arguments made for crashing when accessing a non-existent index:
- fast
- shows bugs quickly

Arguments made in favor of returning an optional by default:
- safe (as in "doesn't crash")
- similar to what other modern languages do
- what an unexperienced Swift developer would expect

All are valid arguments, but for different use cases.
In my opinion, the biggest problem is that there's no indication that subscripting can crash on the default array. Alternative subscripts for bounded access wouldn't solve this either.

Maybe Swift should have two different array classes: A fast, fast-failing "UnsafeArray" and a default safe "Array". This would prevent unexpected crashes for new Swift programmers while still providing a faster alternative for those who do low-level stuff. The name "UnsafeArray" would clearly communicate that this class should be handled with care.

- Andreas
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Please find the related proposal which was formed after the long discussion in the list:

https://github.com/luish/swift-evolution/blob/proposal-lenient-collection-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

Thanks; I have seen this and other proposals, but none of them address the problem that most people don’t expect a crash when using subscripting – except for Erica’s excellent suggestion to make subscript throw, which would also require considerable changes to existing code.

- Andreas

Please find the related proposal which was formed after the long
discussion in the list:

https://github.com/luish/swift-evolution/blob/proposal-lenient-collection-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md

Thanks; I have seen this and other proposals, but none of them address
the problem that most people don’t expect a crash when using

"..*most* people don’t expect.." could you prove this please? Perhaps you want to say *many* people. Probably. But the same many people expect this. Especially if they know a little of C language or other language that don't allow to use wrong indexes for arrays.

Also, why they don't expect this when writing in Swift? This behavior described in help/documentation/tutorial for Swift, this is how Swift works with arrays.

subscripting – except for Erica’s excellent suggestion to make subscript
throw, which would also require considerable changes to existing code.

I'm not sure about this idea. Still - if you'll use wrong index your program will crash by thrown exception. Or I don't understand the suggestion.

···

On 23.06.2016 15:48, Andreas Ley wrote:

- Andreas

"..*most* people don’t expect.." could you prove this please?

I should have written “most people I know” or “the people I work with".

Especially if they know a little of C language or other language that don't allow to use wrong indexes for arrays.

Maybe that’s the point: They don’t. And it is my understanding that they shouldn’t need to; that Swift should be for everyone and a great language to get into programming.

This behavior described in help/documentation/tutorial for Swift, this is how Swift works with arrays.

Yes, and I agree with you that people should read the documentation.
However, the question is: Is this behavior optimal? Is a runtime error really the best way to handle this for the most common use case of arrays?
But the definition of “most common use case” varies wildly. Hence my idea to have separate classes for separate needs.

In the end, what’s most important to me is to be able to have a consistent mental model. Something simple like: If I’m using classes called “unsafe” or exclamation marks, my app might experience runtime errors. That’s something the students I’ve taught could understand easily.

- Andreas

"..*most* people don’t expect.." could you prove this please?

I should have written “most people I know” or “the people I work with".

Especially if they know a little of C language or other language that don't allow to use wrong indexes for arrays.

Maybe that’s the point: They don’t. And it is my understanding that they shouldn’t need to; that Swift should be for everyone and a great language to get into programming.

This behavior described in help/documentation/tutorial for Swift, this is how Swift works with arrays.

Yes, and I agree with you that people should read the documentation.
However, the question is: Is this behavior optimal? Is a runtime error really the best way to handle this for the most common use case of arrays?

Yes. If you are reaching out of bounds of the array, there is a computation error (most likely) and the app is in an incosistent state and it's always better to crash than to pretend it's all OK and potentially do some harm to user's data.

If the getter returned an optional, most people would get annoyed really quickly and started just placing ! everywhere, which would make the code the same, without the diagnostic message which index was accessed.

There is only a handful of usecases where it is advantageous to have the behavior described and no one can stop you from creating an extension and adding an accessor method that returns an optional.

AFAIK I don't know any language that is as strongly typed as Swift whose default behavior would be allowing to reach our of the bounds without a runtime error.

···

On Jun 23, 2016, at 4:52 PM, Andreas Ley via swift-evolution <swift-evolution@swift.org> wrote:

But the definition of “most common use case” varies wildly. Hence my idea to have separate classes for separate needs.

In the end, what’s most important to me is to be able to have a consistent mental model. Something simple like: If I’m using classes called “unsafe” or exclamation marks, my app might experience runtime errors. That’s something the students I’ve taught could understand easily.

- Andreas
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution