<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 31, 2017, at 6:54 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">On Tue, Jan 31, 2017 at 6:40 PM, Matthew Johnson <span dir="ltr" class="">&lt;<a href="mailto:matthew@anandabits.com" target="_blank" class="">matthew@anandabits.com</a>&gt;</span> wrote:<br class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><br class=""><div class=""><div class=""><div class="h5"><blockquote type="cite" class=""><div class="">On Jan 31, 2017, at 6:15 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class="m_1304279569520014042Apple-interchange-newline"><div class=""><div dir="ltr" class="">On Tue, Jan 31, 2017 at 6:09 PM, Matthew Johnson <span dir="ltr" class="">&lt;<a href="mailto:matthew@anandabits.com" target="_blank" class="">matthew@anandabits.com</a>&gt;</span> wrote:<br class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><br class=""><div class=""><div class=""><div class="m_1304279569520014042h5"><blockquote type="cite" class=""><div class="">On Jan 31, 2017, at 5:35 PM, Xiaodi Wu via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_1304279569520014042m_-295506938742049236Apple-interchange-newline"><div class=""><div dir="ltr" class="">On Tue, Jan 31, 2017 at 5:28 PM, David Sweeris <span dir="ltr" class="">&lt;<a href="mailto:davesweeris@mac.com" target="_blank" class="">davesweeris@mac.com</a>&gt;</span> wrote:<br class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><br class=""><div class=""><span class=""><blockquote type="cite" class=""><div class="">On Jan 31, 2017, at 2:04 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class="m_1304279569520014042m_-295506938742049236m_4871187344016849002Apple-interchange-newline"><div class=""><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">On Tue, Jan 31, 2017 at 3:36 PM, David Sweeris via swift-evolution<span class="m_1304279569520014042m_-295506938742049236m_4871187344016849002Apple-converted-space">&nbsp;</span><span dir="ltr" class="">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evoluti<wbr class="">on@swift.org</a>&gt;</span><span class="m_1304279569520014042m_-295506938742049236m_4871187344016849002Apple-converted-space">&nbsp;</span>wrote:<br class=""><div class="gmail_extra"><div class="gmail_quote"><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" class=""><span class="m_1304279569520014042m_-295506938742049236m_4871187344016849002gmail-"><div class=""><br class=""></div><div class="">On Jan 31, 2017, at 11:32, Jaden Geller via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><span class="">I think that is perfectly reasonable, but then it seems weird to be able to iterate over it (with no upper bound) independently of a collection). It would surprise me if</span><br class=""><span class="">```</span><br class=""><span class="">for x in arr[arr.startIndex…] { print(x) }</span><br class=""><span class="">```</span><br class=""><span class="">yielded different results than</span><br class=""><span class="">```</span><br class=""><span class="">for i in arr.startIndex… { print(arr[i]) } // CRASH</span><br class=""><span class="">```</span><br class=""><span class="">which it does under this model.</span><br class=""></div></blockquote><br class=""></span><div class="">(I<span class="m_1304279569520014042m_-295506938742049236m_4871187344016849002Apple-converted-space">&nbsp;</span><i class="">think</i><span class="m_1304279569520014042m_-295506938742049236m_4871187344016849002Apple-converted-space">&nbsp;</span>this how it works... semantically, anyway) Since the upper bound isn't specified, it's inferred from the context.</div><div class=""><br class=""></div><div class="">In the first case, the context is as an index into an array, so the upper bound is inferred to be the last valid index.</div><div class=""><br class=""></div><div class="">In the second case, there is no context, so it goes to Int.max. Then,<span class="m_1304279569520014042m_-295506938742049236m_4871187344016849002Apple-converted-space">&nbsp;</span><i class="">after</i><span class="m_1304279569520014042m_-295506938742049236m_4871187344016849002Apple-converted-space">&nbsp;</span>the "wrong" context has been established, you try to index an array with numbers from the too-large range.</div><div class=""><br class=""></div><div class="">Semantically speaking, they're pretty different operations. Why is it surprising that they have different results?</div></div></blockquote><div class=""><br class=""></div><div class="">I must say, I was originally rather fond of `0...` as a spelling, but IMO, Jaden and others have pointed out a real semantic issue.</div><div class=""><br class=""></div><div class="">A range is, to put it simply, the "stuff" between two end points. A "range with no upper bound" _has to be_ one that continues forever. The upper bound _must_ be infinity.</div></div></div></div></div></blockquote><div class=""><br class=""></div></span><div class="">Depends… Swift doesn’t allow partial initializations, and neither the `.endIndex` nor the `.upperBound` properties of a `Range` are optional. From a strictly syntactic PoV, a "Range without an upperBound” can’t exist without getting into undefined behavior territory.</div><div class=""><br class=""></div><div class="">Plus, mathematically speaking, an infinite range would be written "[x, ∞)", with an open upper bracket. If you write “[x, ∞]”, with a <i class="">closed</i> upper bracket, that’s kind of a meaningless statement. I would argue that if we’re going to represent that “infinite” range, the closest Swift spelling would be “x..&lt;“. That leaves the mathematically undefined notation of “[x, ∞]”, spelled as "x…” in Swift, free to let us have “x…” or “…x” (which by similar reasoning can’t mean "(∞, x]”) return one of these:</div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px" class=""><div class=""><div class=""><div style="margin:0px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">enum</span><span style="font-variant-ligatures:no-common-ligatures" class=""> IncompleteRange&lt;T</span><span style="font-variant-ligatures:no-common-ligatures" class="">&gt; {</span></div></div></div><div class=""><div class=""><div style="margin:0px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">case</span><span style="font-variant-ligatures:no-common-ligatures" class=""> upperValue(</span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187" class="">T</span><span style="font-variant-ligatures:no-common-ligatures" class="">)</span></div></div></div><div class=""><div class=""><div style="margin:0px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">case</span><span style="font-variant-ligatures:no-common-ligatures" class=""> lowerValue(</span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187" class="">T)</span></div></div></div><div class=""><div class=""><div style="margin:0px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">}</span></div></div></div></blockquote><div class=""><div class=""><div class=""><span style="font-variant-ligatures:no-common-ligatures" class="">which we could then pass to the subscript function of a collection to create the actual Range like this:</span></div></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px" class=""><div class=""><div class=""><div class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(112,61,170)" class=""><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">extension</span><span style="font-variant-ligatures:no-common-ligatures" class=""> </span><span style="font-variant-ligatures:no-common-ligatures" class="">Collection</span><span style="font-variant-ligatures:no-common-ligatures" class=""> {</span></div></span></div></div></div><div class=""><div class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><div style="margin:0px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">subscript</span><span style="font-variant-ligatures:no-common-ligatures" class="">(</span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">_</span><span style="font-variant-ligatures:no-common-ligatures" class=""> ir: </span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187" class="">IncompleteRange</span><span style="font-variant-ligatures:no-common-ligatures" class="">&lt;Index&gt;) -&gt; SubSequence {</span></div></span></div></div><div class=""><div class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><div style="margin:0px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">switch</span><span style="font-variant-ligatures:no-common-ligatures" class=""> ir {</span></div></span></div></div><div class=""><div class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><div style="margin:0px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">case</span><span style="font-variant-ligatures:no-common-ligatures" class=""> .</span><span style="font-variant-ligatures:no-common-ligatures;color:#31595d" class="">lowerValue</span><span style="font-variant-ligatures:no-common-ligatures" class="">(</span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">let</span><span style="font-variant-ligatures:no-common-ligatures" class=""> lower): </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">return</span><span style="font-variant-ligatures:no-common-ligatures" class=""> </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">self</span><span style="font-variant-ligatures:no-common-ligatures" class="">[lower ..&lt; </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">self</span><span style="font-variant-ligatures:no-common-ligatures" class="">.</span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="">endIndex</span><span style="font-variant-ligatures:no-common-ligatures" class="">]</span></div></span></div></div><div class=""><div class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><div style="margin:0px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">case</span><span style="font-variant-ligatures:no-common-ligatures" class=""> .</span><span style="font-variant-ligatures:no-common-ligatures;color:#31595d" class="">upperValue</span><span style="font-variant-ligatures:no-common-ligatures" class="">(</span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">let</span><span style="font-variant-ligatures:no-common-ligatures" class=""> upper): </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">return</span><span style="font-variant-ligatures:no-common-ligatures" class=""> </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">self</span><span style="font-variant-ligatures:no-common-ligatures" class="">[</span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2" class="">self</span><span style="font-variant-ligatures:no-common-ligatures" class="">.</span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa" class="">startIndex</span><span style="font-variant-ligatures:no-common-ligatures" class=""> ..&lt; upper]</span></div></span></div></div><div class=""><div class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><div style="margin:0px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; }</span></div></span></div></div><div class=""><div class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><div style="margin:0px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">&nbsp; &nbsp; }</span></div></span></div></div><div class=""><div class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><div style="margin:0px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">}</span></div></span></div></div></blockquote></div></blockquote><div class=""><br class=""></div><div class="">I understand that you can do this from a technical perspective. But I'm arguing it's devoid of semantics.&nbsp; That is, it's a spelling to dress up a number.</div></div></div></div></div></blockquote><div class=""><br class=""></div></div></div><div class="">It’s not any more devoid of semantics than a partially applied function.</div></div></div></blockquote><div class=""><br class=""></div><div class="">Yes, but this here is not a partially applied type.</div><div class=""><br class=""></div><div class="">Nor does it square with your proposal that you should be able to use `for i in 0...` to mean something different from `array[0...]`. We don't have partially applied functions doubling as function calls with default arguments.</div></div></div></div></div></blockquote><div class=""><br class=""></div></div></div><div class="">I’m not trying to say it’s *exactly* like a partially applied function.</div></div></div></blockquote><div class=""><br class=""></div><div class="">I'm not saying you're arguing that point. I'm saying that there is a semantic distinction between (1) a range with two bounds where you've only specified the one, and (2) a range with one bound. There must be an answer to the question: what is the nature of the upper bound of `0...`? Either it exists but is not yet known, or it is known that it does not exist (or, it is not yet known whether or not it exists). But these are not the same thing!</div><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><span class=""><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class="">It is a number or index with added semantics that it provides a lower (or upper) bound on the possible value specified by its type.</div><span class=""><br class=""><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div><div class="">What is such an `IncompleteRange&lt;T&gt;` other than a value of type T? It's not an upper bound or lower bound of anything until it's used to index a collection. Why have a new type (IncompleteRange&lt;T&gt;), a new set of operators (prefix and postfix range operators), and these muddied semantics for something that can be written `subscript(upTo upperBound: Index) -&gt; SubSequence { ... }`? _That_ has unmistakable semantics and requires no new syntax.</div></div></div></div></blockquote><div class=""><br class=""></div></span><div class="">Arguing that it adds too much complexity relative to the value it provides is reasonable.&nbsp; The value in this use case is mostly syntactic sugar so it’s relatively easy to make the case that it doesn’t cary its weight here.</div><div class=""><br class=""></div><div class="">The value in Ben’s use case is a more composable alternative to `enumerated`.&nbsp; I find this to be a reasonably compelling example of the kind of thing a partial range might enable.</div></div></div></blockquote><div class=""><br class=""></div><div class="">Ben's use case is not a "partial range." It's a bona fide range with no upper bound.</div></div></div></div></blockquote><div class=""><br class=""></div></span><div class="">Ok, fair enough.&nbsp; Let’s call it an infinite range then.</div><div class=""><br class=""></div><div class="">We can form an infinite range with an Index even if it’s an opaque type that can’t be incremented or decremented.&nbsp; All we need is a comparable Bound which all Indices meet.&nbsp; We can test whether other indices are contained within that infinite range and can clamp it to a tighter range as well.&nbsp; This clamping is what would need to happen when an infinite range is passed to a collection subscript by providing an upper bound. &nbsp;</div><div class=""><br class=""></div><div class="">The only thing unusual about this is that we don’t usually do a bounds check of any kind when subscripting a collection.</div></div></blockquote><div class=""><br class=""></div><div class="">Precisely. This would be inconsistent. If lenient subscripts as once proposed were accepted, however, then perhaps `arr[lenient: 0...]` would make sense.</div><div class=""><br class=""></div><div class="">But that's not getting to the biggest hitch with your proposal. If subscript were lenient, then `arr[lenient: 42...]` would also have to give you a result even if `arr.count == 21`.</div></div></div></div></div></blockquote><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div><div class="">This is not at all what Dave Abrahams was proposing, though (unless I totally misunderstand). He truly doesn't want an infinite range. He wants to use a terser notation for saying: I want x to be the lower bound of a range for which I don't yet know (or haven't bothered to find out) the finite upper bound. It would be plainly clear, if spelled as `arr[from: 42]`, that if `arr.count &lt; 43` then this expression will trap, but if `arr.count &gt;= 43` then this expression will give you the rest of the elements.</div></div></div></div></div></blockquote><div><br class=""></div><div>Right. &nbsp;I was not making the necessary distinction between incomplete ranges and infinite ranges. &nbsp;Jaden provided an accurate description of what I was trying to get at and it *does* require both `IncompleteRange` and `InfiniteRange` to do it properly.</div><div><br class=""></div><div>I’m not necessarily trying to argue that we *should* do this, only that there isn’t a fundamental semantic problem with it. &nbsp;In a language like Swift there is no fundamental reason that `0…` must semantics independent of context. &nbsp;Allowing context to provide the semantics doesn’t seem any more magical than allowing context to define the type of literals like `0`.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><span class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class="">I also tend to find concise notation important for clarity as long as it isn’t obscure or idiosyncratic.&nbsp; With that in mind, I think I lean in favor of `…` so long as we’re confident we won’t regret it if / when we take up variadic generics and / or tuple unpacking.</div><span class=""><br class=""><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div></div><br class=""></div></div>
______________________________<wbr class="">_________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/mailma<wbr class="">n/listinfo/swift-evolution</a><br class=""></blockquote></span></div><br class=""></div></blockquote></div><br class=""></div></div>
</div></blockquote></span></div><br class=""></div></blockquote></div><br class=""></div></div>
</div></blockquote></div><br class=""></body></html>