Why does Array subscript fail at runtime?


(H. Kofi Gumbs) #1

Hello Swift community,

Here's a philosophy I've struggled with since I started learning Swift. In
general, it seems that failable function calls return `Optional`s; however,
`Array`s violate this rule by failing fast at runtime. I understand that
subscripts can't throw, so the only way to fail fast is to do so at
runtime. I also realize that there are many implementations of the
`array[safe: index]` that I could choose to use instead. However, I do not
understand why the default behavior is still to fail at runtime. Especially
given how they are often introduced as a beginner-friendly data structure.
Am I missing some language philosophy or major decision?

Thanks


(Jeff Kelley) #2

If I’m not mistaken, the main reason for Swift arrays being unsafe in this way is for performance. Checking each subscript would be expensive in a large loop; it’s much more performant to loop from the array’s start index to its end index.

Jeff Kelley

SlaunchaMan@gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan> | jeffkelley.org <http://jeffkelley.org/>

···

On Jul 20, 2016, at 9:07 PM, H. Kofi Gumbs via swift-users <swift-users@swift.org> wrote:

Hello Swift community,

Here's a philosophy I've struggled with since I started learning Swift. In general, it seems that failable function calls return `Optional`s; however, `Array`s violate this rule by failing fast at runtime. I understand that subscripts can't throw, so the only way to fail fast is to do so at runtime. I also realize that there are many implementations of the `array[safe: index]` that I could choose to use instead. However, I do not understand why the default behavior is still to fail at runtime. Especially given how they are often introduced as a beginner-friendly data structure. Am I missing some language philosophy or major decision?

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


(Chéyo Jiménez) #3

Making Array<T> subscript access return T? or T! instead of T. The current array behavior is intentional <http://article.gmane.org/gmane.comp.lang.swift.evolution/11277>: it accurately reflects the fact that out-of-bounds array access is a logic error, and changing the current behavior would slow Arrayaccesses to an unacceptable degree. This topic has come up multiple <http://thread.gmane.org/gmane.comp.lang.swift.evolution/3651> times <http://thread.gmane.org/gmane.comp.lang.swift.evolution/19793> before <http://thread.gmane.org/gmane.comp.lang.swift.evolution/21420>, but is very unlikely to be accepted.

https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md

···

On Jul 20, 2016, at 9:07 PM, H. Kofi Gumbs via swift-users <swift-users@swift.org> wrote:

Hello Swift community,

Here's a philosophy I've struggled with since I started learning Swift. In general, it seems that failable function calls return `Optional`s; however, `Array`s violate this rule by failing fast at runtime. I understand that subscripts can't throw, so the only way to fail fast is to do so at runtime. I also realize that there are many implementations of the `array[safe: index]` that I could choose to use instead. However, I do not understand why the default behavior is still to fail at runtime. Especially given how they are often introduced as a beginner-friendly data structure. Am I missing some language philosophy or major decision?

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


(Zhao Xin) #4

For Array, it is easy to know its boundary. And it is an error when
accessing indices out of the boundary. Returning a nil makes your app hard
to trace bugs.

Array's subscript function returns Element instead of Element?. It is
common and aligns with the other languages. You question seems odd to me.

Zhaoxin

···

On Thu, Jul 21, 2016 at 12:07 PM, H. Kofi Gumbs via swift-users < swift-users@swift.org> wrote:

Hello Swift community,

Here's a philosophy I've struggled with since I started learning Swift.
In general, it seems that failable function calls return `Optional`s;
however, `Array`s violate this rule by failing fast at runtime. I
understand that subscripts can't throw, so the only way to fail fast is to
do so at runtime. I also realize that there are many implementations of the
`array[safe: index]` that I could choose to use instead. However, I do not
understand why the default behavior is still to fail at runtime. Especially
given how they are often introduced as a beginner-friendly data structure.
Am I missing some language philosophy or major decision?

Thanks

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


(H. Kofi Gumbs) #5

Thanks to everyone who responded! Particularly Jose who provided links to
the Swift evolution discussion, one of which is still open, though deferred
from Swift 3. I'm adding some thoughts to individual contents below, but my
original question was answered.

Jeff, that makes sense after looking more closely at the source. I had
incorrectly assumed that the fatal error was happening in Swift code, but I
believe it is in the C++.

Brent, I've seen examples like that before, and I think I just might be
unable to see the forest for the trees. `map` seems like the clearly better
choice for the first two transformations. I haven't done any Cocoa
development, however, so I have no opinion to share there. In general,
though it does seem like `enumerated` should be adequate when people want
to have guaranteed values.

Zhou, allowing clients to handle bad accesses would certainly not cause
bugs. In the worst case, developers would litter ! around their array
accesses, and the same crashes that existed before will continue. The fact
that something similar happens in other languages is similarly
unconvincing. There are languages where this is not the case (Elm).

···

On Wed, Jul 20, 2016 at 10:07 PM H. Kofi Gumbs <h.kofigumbs@gmail.com> wrote:

Hello Swift community,

Here's a philosophy I've struggled with since I started learning Swift.
In general, it seems that failable function calls return `Optional`s;
however, `Array`s violate this rule by failing fast at runtime. I
understand that subscripts can't throw, so the only way to fail fast is to
do so at runtime. I also realize that there are many implementations of the
`array[safe: index]` that I could choose to use instead. However, I do not
understand why the default behavior is still to fail at runtime. Especially
given how they are often introduced as a beginner-friendly data structure.
Am I missing some language philosophy or major decision?

Thanks


(Tim Vermeulen) #6

The Collection(Type) protocol requires a subscript that returns a non-optional, so it’s just not arrays. The idea is that a startIndex and endIndex are provided, after which you can guarantee that subscripting the collection with any index in the range startIndex ..< endIndex is valid. This isn’t the case for dictionaries, for instance.

Using ! excessively is *not* a good idea. It will give people the idea that it’s okay to force unwrap optionals. Ideally, you’d never have to force unwrap because values shouldn’t be optional if you’re sure they contain a value (if you know that the array index is within range, for example).

···

Thanks to everyone who responded! Particularly Jose who provided links to
the Swift evolution discussion, one of which is still open, though deferred
from Swift 3. I'm adding some thoughts to individual contents below, but my
original question was answered.

Jeff, that makes sense after looking more closely at the source. I had
incorrectly assumed that the fatal error was happening in Swift code, but I
believe it is in the C++.

Brent, I've seen examples like that before, and I think I just might be
unable to see the forest for the trees. `map` seems like the clearly better
choice for the first two transformations. I haven't done any Cocoa
development, however, so I have no opinion to share there. In general,
though it does seem like `enumerated` should be adequate when people want
to have guaranteed values.

Zhou, allowing clients to handle bad accesses would certainly not cause
bugs. In the worst case, developers would litter ! around their array
accesses, and the same crashes that existed before will continue. The fact
that something similar happens in other languages is similarly
unconvincing. There are languages where this is not the case (Elm).

On Wed, Jul 20, 2016 at 10:07 PM H. Kofi Gumbs<h.kofigumbs at gmail.com> > wrote:

> Hello Swift community,
>
> Here's a philosophy I've struggled with since I started learning Swift.
> In general, it seems that failable function calls return `Optional`s;
> however, `Array`s violate this rule by failing fast at runtime. I
> understand that subscripts can't throw, so the only way to fail fast is to
> do so at runtime. I also realize that there are many implementations of the
> `array[safe: index]` that I could choose to use instead. However, I do not
> understand why the default behavior is still to fail at runtime. Especially
> given how they are often introduced as a beginner-friendly data structure.
> Am I missing some language philosophy or major decision?
>
> Thanks