[swift-evolution] Strings in Swift 4

Xiaodi Wu xiaodi.wu at gmail.com
Tue Jan 31 18:15:03 CST 2017


On Tue, Jan 31, 2017 at 6:09 PM, Matthew Johnson <matthew at anandabits.com>
wrote:

>
> On Jan 31, 2017, at 5:35 PM, Xiaodi Wu via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> On Tue, Jan 31, 2017 at 5:28 PM, David Sweeris <davesweeris at mac.com>
> wrote:
>
>>
>> On Jan 31, 2017, at 2:04 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>
>> On Tue, Jan 31, 2017 at 3:36 PM, David Sweeris via swift-evolution <
>> swift-evolution at swift.org> wrote:
>>
>>>
>>> On Jan 31, 2017, at 11:32, Jaden Geller via swift-evolution <
>>> swift-evolution at 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): 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.
>

Yes, but this here is not a partially applied type.

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.


> 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.
>
>
> 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.
>

Ben's use case is not a "partial range." It's a bona fide range with no
upper bound.


> 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 at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170131/a5d8d79a/attachment.html>


More information about the swift-evolution mailing list