<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="">With a lot of these new features, it helps me greatly to see them in action. I've built a poor man's version of these incomplete ranges in a Swift Sandbox here:<div class=""><span class="Apple-tab-span" style="white-space:pre">        </span><a href="http://swiftlang.ng.bluemix.net/#/repl/58925f5d42b65e6dce9a5bea" class="">http://swiftlang.ng.bluemix.net/#/repl/58925f5d42b65e6dce9a5bea</a></div><div class=""><br class=""></div><div class="">This implementation suffers greatly from a lack of generic subscripts, and the type names are terrible and not at all suggestions. Otherwise, as far as I can tell, the <i class="">behavior</i> of the one-sided ranges correctly matches what Ben is describing here — if you're unsure about how this will look and behave in practice, please take a look.</div><div class=""><br class=""></div><div class="">Nate</div><div class=""><br class=""></div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Feb 1, 2017, at 10:37 AM, Ben Cohen via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="auto" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class="Apple-interchange-newline">I think Dave has already made these points separately but it probably helps to recap more explicitly the behavior we expect from “x…"</div><div class=""><br class=""></div><div class="">Names are just for discussion purposes, exact naming can be left as a separate discussion from functionality:</div><div class=""><br class=""></div><div class="">- Informally, one-sided ranges are a thing. Formally, there are lower-bounded one-sided ranges, which are created with a postfix ... operator. For now, let’s just fully understand them and come back to upper-bounded ranges later.</div><div class="">- Collections will have a subscript that takes a one-sided range and returns a SubSequence. The behavior of that subscript is that the collection "fills in" the “missing” side with it’s upper/lower bound and uses that two-sided range to return a slice.*</div><div class="">- When the Bound type of a lower-bounded range is countable, it will conform to Sequence.** The behavior of that sequence’s iterator is that it starts at the lower bound, and increments indefinitely.</div><div class="">- One-sided ranges should have ~= defined for use with switch statements, where any value above the bound for a lower-bounded range would return true.</div><div class=""><br class=""></div><div class="">* implementation detail: collections would probably have a generic subscript taking a type conforming to RangeExpression, and that protocol would have a helper extension for filling in the missing range given a collection</div><div class=""><div class="">**one-sided ranges ought in fact to be infinite Collections… a concept that needs a separate thread</div></div><div class=""><br class=""></div><div class="">With that defined:</div><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Feb 1, 2017, at 5:02 AM, Xiaodi Wu via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class="">I entirely agree with you on the desired behavior of `zip(...)`.<br class=""><br class="">However, if you insist on 0... being notionally an infinite range, then you would have to insist on `for i in 0...` also trapping. Which is not a big deal, IMO, but will surely make the anti-trapping crowd upset.<br class=""><br class=""></div></blockquote><div class=""><br class=""></div><div class="">Certainly, for i in 0… would trap once the iterator needs to increment past Int.max. If you break out of the loop before this happens, it won’t trap. The statement is the moral equivalent of a C-style for(i = 0; /*nothing*/ ; ++i).</div><div class=""><br class=""></div><div class="">If the anti-trapping crowd are upset, they should be upset with Int, not this range type. The range has no opinion on trapping – its iterator just increments its Bounds type when asked to.</div><br class=""><blockquote type="cite" class=""><div class="">The bigger issue is that either you must have a lenient/clamping subscript for `arr[0...]` or it too must trap, which is not desired.<span class="Apple-converted-space"> </span></div></blockquote><div class=""><br class=""></div><div class="">Based on the definition I give above, arr[0…] means “from 0 up to the endIndex of arr”. This will not trap.</div><div class=""><br class=""></div><div class="">(there is a legitimate quibble here that this will translate into arr[0..<arr.endIndex], but the … kind of implies arr[0…arr.endIndex] which is invalid. But 0..< is ugly so we should ignore this quibble for the sake of aesthetics)</div><div class=""><br class=""></div><blockquote type="cite" class=""><div class="">However, if `arr[0...]` is clamping, then `[1, 2, 3][100...]` would not trap and instead give you `[]`.<br class=""><br class=""></div></blockquote><div class=""><br class=""></div><div class="">It should trap, because 100..<arr.endIndex is not a valid argument for slicing this array.</div><div class=""><br class=""></div><blockquote type="cite" class=""><div class="">If 0... is regarded as an incomplete range, your example of `zip(...)` could still trap as desired. It would trap on the notional attempt to assign someArray.count to IncompleteRange<T>.inferredUpperBound if count exceeds T.max.<span class="Apple-converted-space"> </span></div></blockquote><div class=""><br class=""></div><div class="">It’s unclear to me whether you are trying to formally define .inferredUpperBound as a property you expect to exist, or if you’re using it as informal shorthand. But there is no implied upper bound to a one-sided lower-bounded range, only an actual lower bound. Operations taking lower-bounded ranges as arguments can infer their own upper bound from context, or not, depending on the functionality they need.</div><div class=""><br class=""></div><div class="">As an example of an alternative inferred upper bound: suppose you want to define your own ordering for ranges, for sorting/display purposes. You decide on a lexicographic ordering first by lower then upper bound. You want one-sided ranges to fit into this ordering. So you infer the upper bound to be infinite, for sorting purposes, so: 0…5 < 0… < 1…4 < 1…5 < 1…. This does not mean the upper bound is implied to be infinite, just that the sorting predicate infers it to be, for the purpose of sorting.</div><br class=""><blockquote type="cite" class=""><div class="">With such semantics for 0..., [1, 2, 3][0...] would behave as expected without the need for leniency, but [1, 2, 3][100...] would trap as I assume you'd expect.<span class="Apple-converted-space"> </span></div></blockquote><div class=""><br class=""></div><div class="">[1,2,3][0…] is valid because the array has an index of 0, but [100…] isn’t because it doesn’t.</div><div class=""><br class=""></div><div class="">It’s worth noting the difference with Python here. In Python, [][2:] is valid because [][2:n] is valid (both return []). In Swift, [][2…] should be invalid (trap) because [][2..<n] is invalid.</div><br class=""><blockquote type="cite" class=""><div class="">However, it would make no sense to write `for i in 0...`.<br class=""><br class=""></div></blockquote><div class=""><br class=""></div><div class="">I don’t see how. But regardless, the definition of how countable lower-bounded ranges conform to Sequence is just something to be defined in some way that is useful and intuitive to users. 0… being an indefinitely increasing sequence seems like it’s intuitive to me, as does a[n…] being “a slice from n to the end”.</div><div class=""><br class=""></div><div class="">That definition does not need to be unearthed based on some underlying principles. Defining behavior based on building upon axioms is a useful approach sometimes, but if at any point we are finding they get in the way of implementations within the std lib being intuitive or useful, we should stop trying to bend over backwards to stick with this approach.</div><div class=""><br class=""></div><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div class="gmail_quote"><div dir="ltr" class="">On Tue, Jan 31, 2017 at 21:39 Dave Abrahams <<a href="mailto:dabrahams@apple.com" class="">dabrahams@apple.com</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><br class="gmail_msg">on Tue Jan 31 2017, Xiaodi Wu <<a href="http://xiaodi.wu-at-gmail.com/" rel="noreferrer" class="gmail_msg" target="_blank">xiaodi.wu-AT-gmail.com</a>> wrote:<br class="gmail_msg"><br class="gmail_msg">> But that's not getting to the biggest hitch with your proposal. If<br class="gmail_msg">> subscript were lenient, then `arr[lenient: 42...]` would also have to give<br class="gmail_msg">> you a result even if `arr.count == 21`.<br class="gmail_msg">><br class="gmail_msg">> This is not at all what Dave Abrahams was proposing, though (unless I<br class="gmail_msg">> totally misunderstand). He truly doesn't want an infinite range. He wants<br class="gmail_msg">> to use a terser notation for saying: I want x to be the lower bound of a<br class="gmail_msg">> range for which I don't yet know (or haven't bothered to find out) the<br class="gmail_msg">> finite upper bound. It would be plainly clear, if spelled as `arr[from:<br class="gmail_msg">> 42]`, that if `arr.count < 43` then this expression will trap, but if<br class="gmail_msg">> `arr.count >= 43` then this expression will give you the rest of the<br class="gmail_msg">> elements.<br class="gmail_msg"><br class="gmail_msg">I think you do misunderstand. Notionally, 0... is an infinite range.<br class="gmail_msg">The basic programming model for numbers in swift is (to a first<br class="gmail_msg">approximation), program as if there's no overflow, and we'll catch you<br class="gmail_msg">by trapping if your assumption is wrong. It doesn't make sense for the<br class="gmail_msg">semantics of 0... to depend on the deduced type of 0 or the<br class="gmail_msg">representable range of Int<br class="gmail_msg"><br class="gmail_msg">for example,<br class="gmail_msg"><br class="gmail_msg"> for x in zip(n..., someArray) {<br class="gmail_msg"><br class="gmail_msg"> }<br class="gmail_msg"><br class="gmail_msg">How many iterations should this give you? If it doesn't process all of<br class="gmail_msg">someArray, I want a trap.<br class="gmail_msg"><br class="gmail_msg">--<br class="gmail_msg">-Dave<br class="gmail_msg"></blockquote></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class=""></div><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">_______________________________________________</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">swift-evolution mailing list</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="mailto:swift-evolution@swift.org" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">swift-evolution@swift.org</a><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div><br class=""></div></body></html>