<div dir="ltr">Jordan, I think the inspiration here might come from Ruby. I must admit that seeing that `Array.first` returns an optional, but Array#subscript raises a runtime error when the index is out of bounds threw me for a loop. In Ruby, both Array#first and Array.subscript return an optional.<div><br></div><div>If one of the original tenets of swift was to provide greater compile-time null-safety, which it definitely seems it was given the commendable emphasis on optionals being easy to use, then returning an optional would be a solid way to go about subscripting. Think of it this way: when I call a method with nullable return value, I am forced to deal with the fact that the method can fail at compile time. When I subscript an array, I am not forced to deal with it at compile time, and it will fail at runtime instead.</div><div><br></div><div>Nullable subscripting is a big departure from the way most modern languages do things and that is why I don't blame you for rejecting it. That said, it is a pleasant change in the way you think about subscripting.</div><div><br></div><div>As a closing thought, subscripting hashes returns an optional value. You might consider this a pretty big inconsistency with arrays. Let me flip your argument against optional array subscripting, for dictionaries: <span style="line-height:1.5"><b>When you are performing a subscript where the key is out of the key set, is it not a programmer error?</b></span></div></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Dec 14, 2015 at 4:54 PM Jordan Rose via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi, Daniel. Thanks for bringing this up. May I ask where you would use a "safe" subscript? When are you performing a subscript where the bounds being…um, out-of-bound…is not a programmer error?<br>
<br>
As for the second half of this, we deliberately decided to not make the subscript operator "smart" (handling negative indexes and such) because extra branches can do very bad things to performance, and because allowing negative indexes sometimes hide bugs. It's also not meaningful for collections whose indexes are not integers.<br>
<br>
Best,<br>
Jordan<br>
<br>
> On Dec 14, 2015, at 12:52, Daniel Duan via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:<br>
><br>
><br>
> In CollectionType, a `Range` is accepted as the argument in a version of `subscript`, which returns a subsequence.<br>
><br>
> [1,2,3,4][2...3] // [3, 4]<br>
><br>
> `subscript` raises a fatal error if the range is out of bound, which is really a side-effect from accessing an element with an out of bound index. This behavior forces users to check bounds beforehand. It has been serving us well.<br>
><br>
> I propose adding a new interface where user can recover from/defer out of bound error in this context. Here are two potential approaches.<br>
><br>
> Approach #1 is more conservative, we add a throwing version of `subscript`. It throws an error if the range is out of bound. We can give the range parameter a name for distinction, resulting usage would look like:<br>
><br>
> do {<br>
> let gimme = [1,2,3,4][safe: 2...4]<br>
> } catch {<br>
> recover()<br>
> }<br>
><br>
> As an alternative, we can replace the original `subscript` with this version, breaking backward compatibilty.<br>
><br>
> Apporoach #2 is a really sweet syntax sugar. We add a new subscript that accepts 2 arugments:<br>
><br>
> extension CollectionType where Self.Index: RandomAccessIndexType {<br>
> public subscript(start:Int?, end:Int?) -> Self.SubSequence { ... }<br>
> }<br>
><br>
> This version would make ANY combination of arugment safe by enabling a sematic similar to Python's slicing mechanism. Explanations come after these examples:<br>
><br>
> [0,1,2,3][1, -1] // [1, 2]<br>
> ["H","e","l","l","o"][-1000, nil] // ["H","e","l","l","o"]<br>
> [1,2,3,4,5,6,7,8][1,5][2,3] // [4]<br>
><br>
> This should look familiar to Python users:<br>
><br>
> * the access is always clamped in-bound. Interpret out-of-bound number as the boundary. [1,2,3][0: 100] means [1,2,3][0: 2].<br>
> * nil indicate the boundary itself. [1,2,3][0: nil] means [1,2,3][0: 2]<br>
> * negative index counts from the end of the sequence. [1,2,3][-2, -1] means [1,2,3][(3-2), (3-1)]<br>
><br>
> Admittedly, this syntax suger seems a little out-of-place in Swift :P<br>
><br>
> Both approaches require just a little of work. As an example, here's one implementation of the 2nd: <a href="https://github.com/dduan/Lic/blob/master/Lic/Lic.swift" rel="noreferrer" target="_blank">https://github.com/dduan/Lic/blob/master/Lic/Lic.swift</a> (please ignore the extension for String, that'd be in a separate proposal, if any).<br>
><br>
><br>
> What do you think?<br>
><br>
> - Daniel Duan<br>
> _______________________________________________<br>
> swift-evolution mailing list<br>
> <a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
> <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br>
_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</blockquote></div>