[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:55:36 CDT 2016


Hmm. I'm also having second thoughts about that Fix-It. I wonder if the
"fix" that's automatically provided is little more than "press here to make
the red thingy go away and do nothing else."

The way I see it, if the error is restricted to mismatched labels, then the
presumption is that someone got the order of the labels wrong. So the error
is basically: "Hey, we think you accidentally swapped your labels. Do you
want us to fix it?" And the default fix, which some people are guaranteed
to choose without even reading the error very carefully, shouldn't be
"Leave the labels swapped even though it looks wrong, and just rewrite that
line so the error disappears!"
On Mon, May 9, 2016 at 05:09 Xiaodi Wu <xiaodi.wu at gmail.com> wrote:

> 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/029bd656/attachment.html>


More information about the swift-evolution mailing list