<div dir="ltr">On Tue, Jan 31, 2017 at 6:15 PM, Jaden Geller <span dir="ltr">&lt;<a href="mailto:jaden.geller@gmail.com" target="_blank">jaden.geller@gmail.com</a>&gt;</span> wrote:<br><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"><br><div><div><div class="h5"><blockquote type="cite"><div>On Jan 31, 2017, at 4:09 PM, Matthew Johnson via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_-4249512996091649943Apple-interchange-newline"><div><div style="word-wrap:break-word"><br><div><blockquote type="cite"><div>On Jan 31, 2017, at 5:35 PM, Xiaodi Wu via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_-4249512996091649943Apple-interchange-newline"><div><div dir="ltr">On Tue, Jan 31, 2017 at 5:28 PM, David Sweeris <span dir="ltr">&lt;<a href="mailto:davesweeris@mac.com" target="_blank">davesweeris@mac.com</a>&gt;</span> wrote:<br><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"><br><div><span><blockquote type="cite"><div>On Jan 31, 2017, at 2:04 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class="m_-4249512996091649943m_4871187344016849002Apple-interchange-newline"><div><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">On Tue, Jan 31, 2017 at 3:36 PM, David Sweeris via swift-evolution<span class="m_-4249512996091649943m_4871187344016849002Apple-converted-space"> </span><span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evoluti<wbr>on@swift.org</a>&gt;</span><span class="m_-4249512996091649943m_4871187344016849002Apple-converted-space"> </span>wrote:<br><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"><span class="m_-4249512996091649943m_4871187344016849002gmail-"><div><br></div><div>On Jan 31, 2017, at 11:32, Jaden Geller via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><span>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><span>```</span><br><span>for x in arr[arr.startIndex…] { print(x) }</span><br><span>```</span><br><span>yielded different results than</span><br><span>```</span><br><span>for i in arr.startIndex… { print(arr[i]) } // CRASH</span><br><span>```</span><br><span>which it does under this model.</span><br></div></blockquote><br></span><div>(I<span class="m_-4249512996091649943m_4871187344016849002Apple-converted-space"> </span><i>think</i><span class="m_-4249512996091649943m_4871187344016849002Apple-converted-space"> </span>this how it works... semantically, anyway) Since the upper bound isn&#39;t specified, it&#39;s inferred from the context.</div><div><br></div><div>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><br></div><div>In the second case, there is no context, so it goes to Int.max. Then,<span class="m_-4249512996091649943m_4871187344016849002Apple-converted-space"> </span><i>after</i><span class="m_-4249512996091649943m_4871187344016849002Apple-converted-space"> </span>the &quot;wrong&quot; context has been established, you try to index an array with numbers from the too-large range.</div><div><br></div><div>Semantically speaking, they&#39;re pretty different operations. Why is it surprising that they have different results?</div></div></blockquote><div><br></div><div>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><br></div><div>A range is, to put it simply, the &quot;stuff&quot; between two end points. A &quot;range with no upper bound&quot; _has to be_ one that continues forever. The upper bound _must_ be infinity.</div></div></div></div></div></blockquote><div><br></div></span><div>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 &quot;Range without an upperBound” can’t exist without getting into undefined behavior territory.</div><div><br></div><div>Plus, mathematically speaking, an infinite range would be written &quot;[x, ∞)&quot;, with an open upper bracket. If you write “[x, ∞]”, with a <i>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 &quot;x…” in Swift, free to let us have “x…” or “…x” (which by similar reasoning can’t mean &quot;(∞, x]”) return one of these:</div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">enum</span><span style="font-variant-ligatures:no-common-ligatures"> IncompleteRange&lt;T</span><span style="font-variant-ligatures:no-common-ligatures">&gt; {</span></div></div></div><div><div><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">case</span><span style="font-variant-ligatures:no-common-ligatures"> upperValue(</span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187">T</span><span style="font-variant-ligatures:no-common-ligatures">)</span></div></div></div><div><div><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">case</span><span style="font-variant-ligatures:no-common-ligatures"> lowerValue(</span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187">T)</span></div></div></div><div><div><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">}</span></div></div></div></blockquote><div><div><div><span style="font-variant-ligatures:no-common-ligatures">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"><div><div><div><span style="font-variant-ligatures:no-common-ligatures"><div style="margin:0px;line-height:normal;font-family:Menlo;color:rgb(112,61,170)"><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">extension</span><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures">Collection</span><span style="font-variant-ligatures:no-common-ligatures"> {</span></div></span></div></div></div><div><div><span style="font-variant-ligatures:no-common-ligatures"><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">    </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">subscript</span><span style="font-variant-ligatures:no-common-ligatures">(</span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">_</span><span style="font-variant-ligatures:no-common-ligatures"> ir: </span><span style="font-variant-ligatures:no-common-ligatures;color:#4f8187">IncompleteRange</span><span style="font-variant-ligatures:no-common-ligatures">&lt;Index&gt;) -&gt; SubSequence {</span></div></span></div></div><div><div><span style="font-variant-ligatures:no-common-ligatures"><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">        </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">switch</span><span style="font-variant-ligatures:no-common-ligatures"> ir {</span></div></span></div></div><div><div><span style="font-variant-ligatures:no-common-ligatures"><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">        </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">case</span><span style="font-variant-ligatures:no-common-ligatures"> .</span><span style="font-variant-ligatures:no-common-ligatures;color:#31595d">lowerValue</span><span style="font-variant-ligatures:no-common-ligatures">(</span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">let</span><span style="font-variant-ligatures:no-common-ligatures"> lower): </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">return</span><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">self</span><span style="font-variant-ligatures:no-common-ligatures">[lower ..&lt; </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">self</span><span style="font-variant-ligatures:no-common-ligatures">.</span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa">endIndex</span><span style="font-variant-ligatures:no-common-ligatures">]</span></div></span></div></div><div><div><span style="font-variant-ligatures:no-common-ligatures"><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">        </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">case</span><span style="font-variant-ligatures:no-common-ligatures"> .</span><span style="font-variant-ligatures:no-common-ligatures;color:#31595d">upperValue</span><span style="font-variant-ligatures:no-common-ligatures">(</span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">let</span><span style="font-variant-ligatures:no-common-ligatures"> upper): </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">return</span><span style="font-variant-ligatures:no-common-ligatures"> </span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">self</span><span style="font-variant-ligatures:no-common-ligatures">[</span><span style="font-variant-ligatures:no-common-ligatures;color:#bb2ca2">self</span><span style="font-variant-ligatures:no-common-ligatures">.</span><span style="font-variant-ligatures:no-common-ligatures;color:#703daa">startIndex</span><span style="font-variant-ligatures:no-common-ligatures"> ..&lt; upper]</span></div></span></div></div><div><div><span style="font-variant-ligatures:no-common-ligatures"><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">        }</span></div></span></div></div><div><div><span style="font-variant-ligatures:no-common-ligatures"><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">    }</span></div></span></div></div><div><div><span style="font-variant-ligatures:no-common-ligatures"><div style="margin:0px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">}</span></div></span></div></div></blockquote></div></blockquote><div><br></div><div>I understand that you can do this from a technical perspective. But I&#39;m arguing it&#39;s devoid of semantics.  That is, it&#39;s a spelling to dress up a number.</div></div></div></div></div></blockquote><div><br></div><div>It’s not any more devoid of semantics than a partially applied function.  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></div></div></div></blockquote><div><br></div></div></div><div>If we treat it as such, we shouldn’t allow users to iterate over it directly:</div><div>```</div><div>for x in 0… { // &lt;- doesn’t make sense; only partially specified</div><div>  print(“hi”)</div><div>}</div><div>```</div><div><br></div><div>We __could__ introduce 2 types, `IncompleteRange` and `InfiniteRange`, providing an overload that constructs each. It would never be ambiguous because `InfiniteRange ` would be the only `Sequence` and `IncompleteRange` would be the only one of these two that is accepted as a collections subscript.</div><div><br></div><div>This *isn’t* that crazy either. There’s precedent for this too. The `..&lt;` operator used to create both ranges and intervals (though it seems those type have started to merge).</div><div><br></div><div>¯\_(ツ)_/¯</div></div></div></blockquote><div><br></div><div><br></div><div>Mercifully, those types have completely merged AFAIK. IMO, the long-term aim should be to have ... and ..&lt; produce only one kind of range.</div><div><br></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"><div><span class=""><blockquote type="cite"><div><div style="word-wrap:break-word"><div><blockquote type="cite"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>What is such an `IncompleteRange&lt;T&gt;` other than a value of type T? It&#39;s not an upper bound or lower bound of anything until it&#39;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><br></div><div>Arguing that it adds too much complexity relative to the value it provides is reasonable.  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><br></div><div>The value in Ben’s use case is a more composable alternative to `enumerated`.  I find this to be a reasonably compelling example of the kind of thing a partial range might enable.</div><div><br></div><div>I also tend to find concise notation important for clarity as long as it isn’t obscure or idiosyncratic.  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><br><blockquote type="cite"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><br></div></div><br></div></div>
______________________________<wbr>_________________<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" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br></blockquote></div><br></div>______________________________<wbr>_________________<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" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br></div></blockquote></span></div><br></div></blockquote></div><br></div></div>