<div dir="ltr"><div>As regards some comments in the <a href="https://github.com/apple/swift-evolution/pull/328" target="_blank">pull request</a> (thanks @Adriano Ferreira), I have updated the <a href="https://github.com/luish/swift-evolution/blob/proposal-lenient-collection-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md#detailed-design" target="_blank">implementation</a> to Swift 3.0. It now uses `<font face="monospace, monospace">clamped(to:)</font>` as suggested by @Nate -- I think it does look much more elegant. :-)</div><div><br></div><div>You can see the current code, run and test it from here: </div><div><a href="https://swiftlang.ng.bluemix.net/#/repl/578ccabaf0ebe4d91be1e605" target="_blank">https://swiftlang.ng.bluemix.net/#/repl/578ccabaf0ebe4d91be1e605</a></div><div><br><div>Considering that there were some other threads and drafts around this very subject, more feedback and discussion are required on this idea. Even with the new Range.clamped(to:) method, I still think that this addition could be handy and useful. I do know that it is a very simple extension and that it doesn't do much behind the scenes, but I would like to have it available and ready to use when convenient. </div><div><br></div><div>Furthermore, it's not all about the "syntax sugar" aspect, it's something to discuss when the fail-fast perspective doesn't apply directly, when the operation doesn't necessarily causes a bug if it fails, when we'd rather have the subscript method executing "safely" (controversial term, but you got my point) than the application crashing in runtime.</div><div><br></div><div>There are many cases where I have to add extra code with operations and validations in order to get subarrays or an element in a specific position. For example, given an application with some sort of "top 5", currently I must be careful and check the array size beforehand. I would rather avoid that and take advantage of a more intuitive and clear solution e.g. `<font face="monospace, monospace">records[clamping: 0..<5]</font>`, instead of validating that the array is not empty and then returning something like `<font face="monospace, monospace">records.count > 5 ? records[0..<5] : records[0..records.count]</font>`.</div></div><div><br></div><div>tl;dr;<b> </b></div><div><br></div><div>After all, I'm just seeking a behaviour that could be compared to what we have for dictionaries when trying to get the value for a non-existing key:</div><div><br></div><div><div><font face="monospace, monospace">let dict = ["a": 1, "b": 2]</font></div><div><b style="font-family:monospace,monospace">> dict["c"] // nil</b><br></div></div><div class="gmail_extra"><br></div><div class="gmail_extra"><div class="gmail_extra"><font face="monospace, monospace">let array = [1,2,3]</font></div><div class="gmail_extra"><font face="monospace, monospace"><b>> array[5] // fatal error: index out of range</b></font></div><div class="gmail_extra"><b style="font-family:monospace,monospace">> array[0..<5] // fatal error: index out of range</b><b style="font-family:monospace,monospace"><br></b></div><div class="gmail_extra"><b style="font-family:monospace,monospace"><br></b></div><div class="gmail_extra"><font face="arial, helvetica, sans-serif">with this proposal:</font></div><div class="gmail_extra"><b style="font-family:monospace,monospace">> array[checking: 5] // nil</b></div><div class="gmail_extra"><b style="font-family:monospace,monospace">> array[checking: 0..<5] // nil (Optional)</b><b style="font-family:monospace,monospace"><br></b></div><div class="gmail_extra"><b style="font-family:monospace,monospace">> array[clamping: 0..<5] // [1,2,3] (clamped to bounds)</b></div></div><div class="gmail_extra"><br clear="all"><div><div data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div style="font-size:small">Regards,</div><div style="font-size:small">Luis<br></div></div></div></div></div></div></div></div></div></div></div></div></div>
<br><div class="gmail_quote">On Tue, May 17, 2016 at 11:54 PM, Nate Cook <span dir="ltr"><<a href="mailto:nate@natecook.com" target="_blank">nate@natecook.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="auto"><span><div><br></div><div>On May 17, 2016, at 5:18 PM, Luis Henrique B. Sousa via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:<br><br></div><blockquote type="cite"><div><div dir="ltr">Many thanks, @Maximilian. I'm also not sure about the performance cost, but I think it is worth it. <div>So I just updated the proposal also including the additional min/max you have suggested (thanks once again):<div><div><a href="https://github.com/apple/swift-evolution/pull/328" target="_blank">https://github.com/apple/swift-evolution/pull/328</a><br><div class="gmail_extra"><br clear="all"><div><div><div dir="ltr"><div><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div style="font-size:small">Best regards,</div><div><br>- Luis</div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></div></blockquote><div><br></div></span>The new Range types have a clamped(to:) method that should do what you need.<div><br></div><div><a href="http://swiftdoc.org/v3.0/type/Range/#func-clamped-to_" target="_blank">http://swiftdoc.org/v3.0/type/Range/#func-clamped-to_</a></div><div><div><div><br></div><div><blockquote type="cite"><div><div dir="ltr"><div><div><div><div class="gmail_extra"><div class="gmail_quote">On Tue, May 17, 2016 at 10:32 PM, Maximilian Hünenberger <span dir="ltr"><<a href="mailto:m.huenenberger@me.com" target="_blank">m.huenenberger@me.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="auto"><div></div><div>While it is true that it uses min and max, you have to add <b style="text-decoration:underline">additional min max</b> in order to achieve the desired behavior.</div><div><br></div><div>So the implementation should be: (also considering (hopefully all) recent naming/index model updates)</div><div><br></div><div><div>// Index is already Comparable</div><div>extension Collection {</div><div><br></div><div> subscript(clamping range: Range<Index>) -> SubSequence {</div><div> // ---> here you have to use the additional min/max</div><div> let start = min(max(startIndex, range.startIndex), endIndex)</div><div> let end = max(min(endIndex, range.endIndex), startIndex)</div><div> return self[start ..< end]</div><div><br></div><div> // ---> or as alternative, probably a bit less performant but Swiftier</div><div> return self[range.clamping(startIndex..<endIndex)]</div><div> }</div><div><br></div><div> subscript(checking range: Range<Index>) -> SubSequence? {</div><div> guard range.startIndex >= startIndex && range.endIndex <= endIndex</div><div> else { return nil }</div><div> return self[range]</div><div> }</div><div><br></div><div> subscript(checking index: Index) -> Generator.Element? {</div><div> // ---> minor syntax update *</div><div> guard self.indices.contains(index)</div><div> else { return nil }</div><div> return self[index]</div><div> }</div><div><br></div><div>}</div></div><div><br></div><div><span style="background-color:rgba(255,255,255,0)">* I'm not sure it is worth the performance cost for arbitrary indices collection with O(n) search. I could imagine Set and Dictionary indices cannot be easily validated in comparison to Array indices. However this approach is more general and handles non trivial index collections where there is no guarantee that any index between startIndex and endIndex is a valid one.</span></div><div><span style="background-color:rgba(255,255,255,0)">The same arguments also apply to `subscript(checking range ...)` where you could validate start and endIndex of the range. </span></div><div><span style="background-color:rgba(255,255,255,0)"><br></span></div><div><span style="background-color:rgba(255,255,255,0)">Best regards</span></div><span><font color="#888888"><div>Maximilian</div></font></span><div><div><div><br>Am 16.05.2016 um 09:45 schrieb Luis Henrique B. Sousa <<a href="mailto:lshsousa@gmail.com" target="_blank">lshsousa@gmail.com</a>>:<br><br></div><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra">Yes. The suggested implementation does use min/max:</div><div class="gmail_extra"><br></div><div class="gmail_extra"><a href="https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md#detailed-design" target="_blank">https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md#detailed-design</a><br clear="all"><div><div><div dir="ltr"><div><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr" style="font-size:small"><br></div><div dir="ltr"></div>- Luis</div></div></div></div></div></div></div></div></div></div>
<br><div class="gmail_quote">On Sun, May 15, 2016 at 3:42 PM, Maximilian Hünenberger <span dir="ltr"><<a href="mailto:m.huenenberger@me.com" target="_blank">m.huenenberger@me.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="auto"><div></div><div>I brought these up because the current implementation produces an error in these cases. You have to insert additional min/max operations.</div><div><div><div><br>Am 15.05.2016 um 16:38 schrieb Luis Henrique B. Sousa <<a href="mailto:lshsousa@gmail.com" target="_blank">lshsousa@gmail.com</a>>:<br><br></div><blockquote type="cite"><div><div dir="ltr"><div class="gmail_extra">Exactly, the idea is to return an empty array just like other languages do. (e.g. python)<br clear="all"><div><div><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr" style="font-size:small"><br></div><div dir="ltr"></div>- Luis</div></div></div></div></div></div></div></div></div>
<br><div class="gmail_quote">On Sun, May 15, 2016 at 10:13 AM, Vladimir.S via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><span>On 15.05.2016 0:09, Maximilian Hünenberger via swift-evolution wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
One point which should be discussed is the following behaviour:<br>
<br>
let array = [0]<br>
// ranges are completely out of bounds and produce an error<br>
array[clamping: 1...2] // error<br>
array[clamping: -2...-1] // error<br>
<br>
Should a range which has no intersection with the indices of the collection<br>
produce an error or just clamp to 0..<0 respectively endIndex..<endIndex?<br>
</blockquote>
<br></span>
I expect it will returns [] i.e. empty array, as no elements with 1...2(-2..-1) indexes in the array. I understand `clamping` similar as 'bounded','in these bounds'. And as soon as [0,1,2,3,4][clamping:2...10] will silently move the right position to allowed index(4), and [0,1,2,3,4][clamping:-2...0] will move left position to 0, I expect that in [0][clamping: 1...2] will try to move both limits to allowed, and as no intersection - silently return empty array.<br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><span>
<br>
Best regards<br>
Maximilian<br>
<br>
Am 13.05.2016 um 17:10 schrieb Luis Henrique B. Sousa via swift-evolution<br></span>
<<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a> <mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>>>:<br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><span>
It seems that there is a consensus that this proposal might be a good<br>
addition to the standard library. All comments on this thread in the past<br>
few weeks were related to naming, not around the behaviour or validity of<br>
the proposed methods. So I will submit this proposal for review very soon<br>
assuming that nobody else has strong arguments against it. :-)<br>
<br>
Proposal: <a href="https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md" rel="noreferrer" target="_blank">https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md</a><br>
<br>
If you have any corrections or suggestions to the proposal text itself,<br>
please comment on this gist:<br>
<a href="https://gist.github.com/luish/832c34ee913159f130d97a914810dbd8" rel="noreferrer" target="_blank">https://gist.github.com/luish/832c34ee913159f130d97a914810dbd8</a><br>
(or pull request to my repo)<br>
<br>
Regards,<br>
<br>
- Luis<br>
<br>
On Tue, May 10, 2016 at 4:13 PM, Luis Henrique B. Sousa<br></span><span>
<<a href="mailto:lshsousa@gmail.com" target="_blank">lshsousa@gmail.com</a> <mailto:<a href="mailto:lshsousa@gmail.com" target="_blank">lshsousa@gmail.com</a>>> wrote:<br>
<br>
Please let me know if you have more suggestions or corrections on<br>
this proposal.<br>
I'm tempted to submit it for review. :-)<br>
<br>
- Luis<br>
<br>
On Tue, May 10, 2016 at 8:53 AM, Luis Henrique B. Sousa<br></span><span>
<<a href="mailto:lshsousa@gmail.com" target="_blank">lshsousa@gmail.com</a> <mailto:<a href="mailto:lshsousa@gmail.com" target="_blank">lshsousa@gmail.com</a>>> wrote:<br>
<br>
It sounds good, thanks for you suggestions @Vladimir, @Patrick<br>
and @Brent.<br>
<br>
I've just updated the proposal:<br>
<a href="https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md#detailed-design" rel="noreferrer" target="_blank">https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md#detailed-design</a><br>
<br>
- Luis<br>
<br>
On Tue, May 10, 2016 at 6:50 AM, Vladimir.S via swift-evolution<br></span><div><div>
<<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a> <mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>>> wrote:<br>
<br>
Yes, I feel like 'within' is much better than 'bounded'.<br>
<br>
How about such changes in proposal:<br>
<br>
a[bounded: -1 ..< 5] --> a[within: -1 ..< 5] (or a[inside:<br>
-1 ..< 5] )<br>
<br>
a[optional: 0 ..< 5] --> a[checking: 0 ..< 5]<br>
a[optional: 5] --> a[checking: 5]<br>
<br>
?<br>
<br>
On 10.05.2016 6:27, Patrick Smith via swift-evolution wrote:<br>
<br>
I like the idea of the of the bounded subscript, however<br>
the optional one I<br>
feel could be used for clumsy code.<br>
<br>
.first and .last have value, but once you start stepping<br>
several arbitrary<br>
indices in, then that code is likely fragile?<br>
<br>
<br>
I can think of ‘within’, ‘inside’ and ‘intersecting’ as<br>
alternative names<br>
for ‘bounded’ that attempt to explain what is going on:<br>
<br>
let a = [1, 2, 3]<br>
<br>
a[within: 0 ..< 5] // [1, 2, 3]<br>
a[inside: 0 ..< 5] // [1, 2, 3]<br>
a[intersecting: 0 ..< 5] // [1, 2, 3]<br>
<br>
<br>
On 28 Apr 2016, at 10:11 PM, Luis Henrique B. Sousa<br>
via swift-evolution<br>
<<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>><br></div></div>
<mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><span><br>
<mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>>>> wrote:<br>
<br>
As we have discussed throughout this thread, the<br>
initial proposal was<br>
modified to include alternative subscript methods<br>
instead of modifying<br>
the default operator/subscript behaviour.<br>
The first draft is<br>
here:<br>
<a href="https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md" rel="noreferrer" target="_blank">https://github.com/luish/swift-evolution/blob/more-lenient-subscripts/proposals/nnnn-more-lenient-collections-subscripts.md</a><br>
<br>
I've also put this as a gist so that you can leave<br>
comments with respect<br>
to the proposal document itself. Any suggestion or<br>
help is very welcome.<br>
<a href="https://gist.github.com/luish/832c34ee913159f130d97a914810dbd8" rel="noreferrer" target="_blank">https://gist.github.com/luish/832c34ee913159f130d97a914810dbd8</a><br>
<br>
Regards,<br>
<br>
- Luis<br>
<br>
On Mon, Apr 11, 2016 at 1:23 PM, Luis Henrique B. Sousa<br>
<<a href="mailto:lshsousa@gmail.com" target="_blank">lshsousa@gmail.com</a> <mailto:<a href="mailto:lshsousa@gmail.com" target="_blank">lshsousa@gmail.com</a>><br></span>
<mailto:<a href="mailto:lshsousa@gmail.com" target="_blank">lshsousa@gmail.com</a><div><div><br>
<mailto:<a href="mailto:lshsousa@gmail.com" target="_blank">lshsousa@gmail.com</a>>>> wrote:<br>
<br>
This proposal seeks to provide a safer ..< (aka<br>
half-open range<br>
operator) in order to avoid **Array index out of<br>
range** errors in<br>
execution time.<br>
<br>
Here is my first draft for this proposal:<br>
<br>
<a href="https://github.com/luish/swift-evolution/blob/half-open-range-operator/proposals/nnnn-safer-half-open-range-operator.md" rel="noreferrer" target="_blank">https://github.com/luish/swift-evolution/blob/half-open-range-operator/proposals/nnnn-safer-half-open-range-operator.md</a><br>
<br>
In short, doing that in Swift causes a runtime error:<br>
<br>
leta =[1,2,3]<br>
letb =a[0..<5]<br>
print(b)<br>
<br>
> Error running code:<br>
> fatal error: Array index out of range<br>
<br>
The proposed solution is to slice the array<br>
returning all elements<br>
that are below the half-open operator, even<br>
though the number of<br>
elements is lesser than the ending of the<br>
half-open operator. So the<br>
example above would return [1,2,3].<br>
We can see this very behaviour in other<br>
languages, such as Python and<br>
Ruby as shown in the proposal draft.<br>
<br>
This would eliminate the need for verifications<br>
on the array size<br>
before slicing it -- and consequently runtime<br>
errors in cases when<br>
the programmer didn't.<br>
<br>
Viewing that it is my very first proposal, any<br>
feedback will be helpful.<br>
<br>
Thanks!<br>
<br>
Luis Henrique Borges<br>
@luishborges<br>
<br>
<br>
_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>><br></div></div>
<mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><span><br>
<mailto:<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>
<br>
<br>
_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a> <mailto:<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> <mailto:<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>
<br>
<br>
_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a> <mailto:<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>
</span></blockquote><span>
<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>
<br>
</span></blockquote><div><div>
_______________________________________________<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>
</div></div></blockquote></div><br></div></div>
</div></blockquote></div></div></div></blockquote></div><br></div></div>
</div></blockquote></div></div></div></blockquote></div><br></div></div></div></div></div>
</div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></div></div></div></div></blockquote></div><br></div></div>