> On Jan 31, 2017, at 4:20 PM, Xiaodi Wu <xiaodi...@gmail.com> wrote: > > On Tue, Jan 31, 2017 at 6:15 PM, Jaden Geller <jaden.gel...@gmail.com > <mailto:jaden.gel...@gmail.com>> wrote: > >> On Jan 31, 2017, at 4:09 PM, Matthew Johnson via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >> >> >>> On Jan 31, 2017, at 5:35 PM, Xiaodi Wu via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>> >>> On Tue, Jan 31, 2017 at 5:28 PM, David Sweeris <daveswee...@mac.com >>> <mailto:daveswee...@mac.com>> wrote: >>> >>>> On Jan 31, 2017, at 2:04 PM, Xiaodi Wu <xiaodi...@gmail.com >>>> <mailto:xiaodi...@gmail.com>> wrote: >>>> >>>> On Tue, Jan 31, 2017 at 3:36 PM, David Sweeris via swift-evolution >>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>>> >>>> On Jan 31, 2017, at 11:32, Jaden Geller via swift-evolution >>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>>> >>>>> 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 >>>>> ``` >>>>> for x in arr[arr.startIndex…] { print(x) } >>>>> ``` >>>>> yielded different results than >>>>> ``` >>>>> for i in arr.startIndex… { print(arr[i]) } // CRASH >>>>> ``` >>>>> which it does under this model. >>>> >>>> (I think this how it works... semantically, anyway) Since the upper bound >>>> isn't specified, it's inferred from the context. >>>> >>>> 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. >>>> >>>> In the second case, there is no context, so it goes to Int.max. Then, >>>> after the "wrong" context has been established, you try to index an array >>>> with numbers from the too-large range. >>>> >>>> Semantically speaking, they're pretty different operations. Why is it >>>> surprising that they have different results? >>>> >>>> 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. >>>> >>>> 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. >>> >>> 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. >>> >>> Plus, mathematically speaking, an infinite range would be written "[x, ∞)", >>> with an open upper bracket. If you write “[x, ∞]”, with a closed 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..<“. 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: >>> enum IncompleteRange<T> { >>> case upperValue(T) >>> case lowerValue(T) >>> } >>> which we could then pass to the subscript function of a collection to >>> create the actual Range like this: >>> extension Collection { >>> subscript(_ ir: IncompleteRange<Index>) -> SubSequence { >>> switch ir { >>> case .lowerValue(let lower): return self[lower ..< self.endIndex] >>> case .upperValue(let upper): returnself[self.startIndex ..< upper] >>> } >>> } >>> } >>> >>> I understand that you can do this from a technical perspective. But I'm >>> arguing it's devoid of semantics. That is, it's a spelling to dress up a >>> number. >> >> 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. > > If we treat it as such, we shouldn’t allow users to iterate over it directly: > ``` > for x in 0… { // <- doesn’t make sense; only partially specified > print(“hi”) > } > ``` > > 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. > > This *isn’t* that crazy either. There’s precedent for this too. The `..<` > operator used to create both ranges and intervals (though it seems those type > have started to merge). > > ¯\_(ツ)_/¯ > > > Mercifully, those types have completely merged AFAIK. IMO, the long-term aim > should be to have ... and ..< produce only one kind of range.
There are still 2 variants (`Range` and `CountableRange`), but I imagine conditional conformances will combine those entirely. (I hope conditional conformances are still in scope for Swift 4. They seem to have a very significant ABI impact.) > >>> What is such an `IncompleteRange<T>` 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<T>), a new set of >>> operators (prefix and postfix range operators), and these muddied semantics >>> for something that can be written `subscript(upTo upperBound: Index) -> >>> SubSequence { ... }`? _That_ has unmistakable semantics and requires no new >>> syntax. >> >> 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. >> >> 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. >> >> 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. >> >>> >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution