> On Jan 31, 2017, at 4:09 PM, Matthew Johnson via swift-evolution 
> <[email protected]> wrote:
> 
> 
>> On Jan 31, 2017, at 5:35 PM, Xiaodi Wu via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 
>> On Tue, Jan 31, 2017 at 5:28 PM, David Sweeris <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>>> On Jan 31, 2017, at 2:04 PM, Xiaodi Wu <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>> 
>>> On Tue, Jan 31, 2017 at 3:36 PM, David Sweeris via swift-evolution 
>>> <[email protected] <mailto:[email protected]>> wrote:
>>> 
>>> On Jan 31, 2017, at 11:32, Jaden Geller via swift-evolution 
>>> <[email protected] <mailto:[email protected]>> 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): return self[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).

¯\_(ツ)_/¯

> 
>> 
>> 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
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to