[swift-evolution] [Pitch] Require tuple conversions to be explicit when labels don't match

Xiaodi Wu xiaodi.wu at gmail.com
Mon May 9 05:09:37 CDT 2016


Two more points to be made:

First, there are types where current behavior allowing implicit erasure and
affixing of labels is a definite win. Consider:

```
typealias CartesianCoordinate = (x: Int, y: Int)
let c: CartesianCoordinate = (0, 1)
print(c.x)

typealias PolarCoordinate = (r: Double, theta: Double)
let p: PolarCoordinate = (0.0, M_PI)
print(p.theta)
```

Second, your examples involving pattern matching are not correct. Since
it's a tuple *pattern*, you'll find that `let (right: e, left: f) = (left:
1, right: 2)` has the same effect as writing `let (left: f, right: e) =
(left: 1, right: 2)`. Which is to say, left goes with left and right goes
with right irrespective of the order of labels on the LHS.


On Mon, May 9, 2016 at 4:00 AM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:

> Also--I didn't read this carefully enough in your initial example--I
> disagree that either (left: Int, right: Int) to (Int, Int) or vice versa
> should require explicit casting, and I think previous conversations on the
> topic showed that at least some on the list felt the same way.
>
> Mismatched labels, yes, because IMO it's alarming without a more explicit
> indication of intent to assume that a user intends to swap labels going
> from (left: Int, right: Int) to (right: Int, left: Int). But to work around
> that restriction, I should be able to erase labels and affix new ones
> without using "as", since no unintentional label swapping can occur in
> either direction.
>
>
> On Mon, May 9, 2016 at 2:57 AM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
>> Hmm, not as sure about that one. To my mind it's a clear expression of
>> intent there. You're saying you know what the labels are and you're
>> choosing not to repeat them. I think it should be on you if you express
>> that intent and you're just plain wrong.
>>
>>
>> On Mon, May 9, 2016 at 2:32 AM, Jacob Bandes-Storch <jtbandes at gmail.com>
>> wrote:
>>
>>> ... and one might also want to require labels when passing values *to* a
>>> labeled tuple:
>>>
>>>     func foo() -> (left: Int, right: Int) {
>>>         return (3, 4)  // error: conversion between tuple types '(Int,
>>> Int)' and '(left: Int, right: Int)' requires explicit 'as' operator
>>>     }
>>>
>>> I've personally been bitten by a typo of this sort (mistakenly swapping
>>> the values) before.
>>> Jacob
>>>
>>> On Mon, May 9, 2016 at 12:23 AM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>>
>>>> A sensible solution, IMO. Error with Fix-It when attempting to convert
>>>> implicitly between tuples with mismatched labels.
>>>>
>>>> On Mon, May 9, 2016 at 01:47 Jacob Bandes-Storch via swift-evolution <
>>>> swift-evolution at swift.org> wrote:
>>>>
>>>>> There was some previous discussion under "[Discussion] Enforce
>>>>> argument labels on tuples
>>>>> <http://thread.gmane.org/gmane.comp.lang.swift.evolution/14910>".
>>>>>
>>>>> Halfway through the thread, Haravikk clearly stated the key point:
>>>>>
>>>>> On Thu, Apr 21, 2016 at 12:14 AM, Haravikk via swift-evolution <
>>>>> swift-evolution at swift.org> wrote:
>>>>>
>>>>>> I think the important thing to remember is that the label check is
>>>>>> intended to prevent cases like this:
>>>>>> let a:(left:Int, right:Int) = (1, 2)
>>>>>> var b:(right:Int, left:Int) = a
>>>>>> While the two tuples are compatible by type, the meaning of the
>>>>>> values may differ due to the different labels; in this case the
>>>>>> values are represented in a different order that a developer should have to
>>>>>> explicitly reverse to ensure they aren’t making a mistake, or they could
>>>>>> represent radically different concepts altogether.
>>>>>
>>>>>
>>>>>
>>>>> I agree there's a potential for confusion here, and I suggest we
>>>>> should add an error (or warning) imploring the user to make the conversion
>>>>> explicit, when the source tuple is labeled:
>>>>>
>>>>>     func foo() -> (left: Int, right: Int) { return (3, 4) }
>>>>>
>>>>>     let (left: a, right: b) = foo()  // ok, labels match
>>>>>
>>>>>     var x = 0, y = 0
>>>>>     (left: x, right: y) = (1, 3)  // ok, source is unlabeled
>>>>>
>>>>>     let (c, d) = foo()
>>>>>     // error: conversion between tuple types '(left: Int, right: Int)'
>>>>> and '(Int, Int)' requires explicit 'as' operator
>>>>>     // suggested fix: "let (c, d) = foo() as (Int, Int)"
>>>>>
>>>>>     let (right: e, left: f) = foo()
>>>>>     // error: conversion between tuple types '(left: Int, right: Int)'
>>>>> and '(right: Int, left: Int)' requires explicit 'as' operator
>>>>>     // suggested fix: "let (right: e, left: f) = foo() as (right: Int,
>>>>> left: Int)"
>>>>>
>>>>>
>>>>> Thoughts?
>>>>>
>>>>> Jacob
>>>>> _______________________________________________
>>>>> 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/20160509/22f5ac26/attachment.html>


More information about the swift-evolution mailing list