[swift-evolution] [Proposal][Discussion] Deprecate Tuple Shuffles

Xiaodi Wu xiaodi.wu at gmail.com
Fri May 5 01:35:47 CDT 2017


On Fri, May 5, 2017 at 1:31 AM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:

> On Fri, May 5, 2017 at 1:21 AM, Robert Widmann <devteam.codafi at gmail.com>
> wrote:
>
>> Those labels anchored the reordering algorithm.  They guaranteed that
>> structural typing thing I brought up where you had to consume all the
>> labels in the type signature before you could continue, but that was where
>> their semantic value ended.  Given an ordering invariant, what matters are
>> the names *you* give to the values in the pattern.  Not the names given
>> in, say, the return value of the function - which as part of the type are
>> supposed to be irrelevant anyways.
>>
>
> There's more to Swift's syntax than what's solely required for the
> compiler to parse it. There are also the bits we put in to help humans
> write correct code.
>
> This is one reason why SE-0111 was revised to permit "cosmetic" labels for
> functions after their type system significance was removed. With respect to
> tuples, I fully understand that if you remove the ability to reorder
> indices of a tuple, labels in tuple patterns won't "do" anything--other
> than assert that the poor human who's writing them has the tuple elements
> in the right order. But that's important. That's valuable.
>

Put concretely:

```
let tuple = (x: 1, y: 2)

// I, silly human, mistakenly think the elements in the tuple are
// `y` first, then `x`. I'm a confused human. Now I write:

let (y: y, x: x) = tuple
// Currently, does the right thing, even though I'm confused.

let (y: y, x: x) = tuple
// Without tuple reordering, this produces an error, which corrects my
confusion.

let (y, x) = tuple
// Oops. I'm out of luck.
```

Enum cases are a different kettle of fish since the last round of proposals
>> (specifically SE-0155).  Associated value clauses are no longer tuples.
>>
>> Thank you for digging up that blog about this too.  I hadn't seen that
>> before I went into this - it came up because of code review related to some
>> fallout from SE-110.
>>
>> ~Robert Widmann
>>
>> 2017/05/05 2:09、Xiaodi Wu <xiaodi.wu at gmail.com> のメッセージ:
>>
>> On Fri, May 5, 2017 at 1:01 AM, Robert Widmann <devteam.codafi at gmail.com>
>> wrote:
>>
>>>
>>>
>>> ~Robert Widmann
>>>
>>> 2017/05/05 1:42、Xiaodi Wu <xiaodi.wu at gmail.com> のメッセージ:
>>>
>>> On Fri, May 5, 2017 at 00:17 Robert Widmann <devteam.codafi at gmail.com>
>>> wrote:
>>>
>>>> On the contrary, this is precisely what it means to deprecate tuple
>>>> shuffles.  You can’t map common parlance onto this term; the proposal and
>>>> the Twitter thread weren’t merely about reordering arguments.
>>>>
>>>
>>> Let's be clear: _all_ of your examples of "shuffles" in the proposal
>>> involve reordering. You defined a tuple shuffle as such: "an undocumented
>>> feature of Swift in which one can re-order the indices of a tuple...." If
>>> you intend to propose a broader change, it is grossly misleading to write
>>> it up in this way.
>>>
>>>
>>> They are both modeled by shuffles.  And we are spinning off into
>>> semantic weeds I'd rather not spin off into.  The core of your
>>> counterargument is the pattern change being bad for business.  Let's
>>> discuss that.
>>>
>>>
>>> but it is entirely another ballgame to remove labels from tuple patterns
>>>> altogether.
>>>>
>>>>
>>>> It’s really not.  Let me demonstrate:
>>>>
>>>> To be clear, are you proposing the prohibition of *adding or removing*
>>>>> labels as well? A previous discussion on tuple shuffling on this list saw
>>>>> consensus that assigning a value of type (label1: T, label2: U) to a
>>>>> variable of type (T, U) and vice versa should absolutely be supported,
>>>>> whether or not reordering is permitted.
>>>>
>>>>
>>>> I am not proposing any changes to switching parameter labels through
>>>> well-typed re-assignments.  This is absolutely still going to be allowed:
>>>>
>>>> var z : (Int, Int) = (0, 0)
>>>> var w : (x : Int, y : Int) = (5, 10)
>>>> z = w
>>>> w = z
>>>>
>>>> This is modeled internally with a tuple shuffle, but not the kind of
>>>> shuffle I’m interested in banning.  It’s a far simpler kind of
>>>>
>>>
>>> What is your proposed behavior for the following code?
>>>
>>> ```
>>> let x: (r: Int, g: Int, b: Int, a: Int) = (255, 255, 255, 0)
>>> let y: (a: Int, r: Int, g: Int, b: Int) = x
>>>
>>> print(y.a) // currently, prints "0"
>>> ```
>>>
>>> Either you are proposing only to remove labels from tuple patterns,
>>> which does not at all prohibit reordering, or you are proposing to prohibit
>>> reordering, in which case this code has an error--or it doesn't and you've
>>> instead _silently_ changed the behavior of existing code. One can live with
>>> warnings and even errors, but a silent change to existing code is the stuff
>>> of nightmares, and I would be strongly opposed to that.
>>>
>>>
>>> This is a reordering.  Banned.  End of story.  This code is fragile and
>>> demonstrates a key reason why we need to enforce an ordering invariant.
>>>
>>>
>>>
>>>>
>>>> And how about *restating* existing labels without any adding or
>>>>> removing? To be clear:
>>>>>
>>>>> ```
>>>>> let (partialValue: v, overflow: o) = 42.addingReportingOverflow(42)
>>>>> ```
>>>>>
>>>>> ...involves absolutely no changes in labels whatsoever. The return
>>>>> type is (partialValue: Int, overflow: ArithmeticOverflow).
>>>>>
>>>>
>>>> That, however, is a kind of shuffle I intend to deprecate here.  This
>>>> kind of pattern is subject to the “arcane syntax” part of the proposal.
>>>>
>>>>
>>>>> Either one of these scenarios is commonly used, and it is astonishing
>>>>> to me that they would be eliminated.
>>>>
>>>>
>>>> Do you have proof of that claim? I have never seen the relevant kinds
>>>> of tuple shuffle used before, and I doubt you have either before today.
>>>>
>>>
>>> Huh? I use it pervasively. Currently, writing out labels during
>>> destructuring guarantees that, even if I've incorrectly memorized the order
>>> of the values in a tuple, the tuple is still destructured as I expect. And
>>> if reordering were not a feature of Swift, I would still write out these
>>> labels. In that case, it would be a static assertion that destructuring is
>>> happening in the expected order. That is, if I try to destructure a tuple
>>> of type (r: Int, g: Int, b: Int, a: Int) and accidentally write 'let (a:
>>> alpha, r: _, g: green, b: _) = ...', I'd get an error and find my mistake
>>> at compile time.
>>>
>>> The whole point of having labels in the first place is clarity at the
>>> point of use. Just as SE-0111 will need revision because it removed a key
>>> documentation use for argument labels, forbidding labels in tuple patterns
>>> would make the same mistake for tuples.
>>>
>>>
>>> The intent at the time may have been to treat tuples as a kind of
>>> structurally-typed thing, but shadowing concerns and reordering in patterns
>>> means this kind of relabeling can be abused and shouldn't be trusted as a
>>> kind of structural invariant in a pattern - as we seem to agree.  To me,
>>> labels in tuple types provide a means of defining custom projections out of
>>> the tuple, nothing more.  In patterns, I don't see a reason for them.
>>>
>>
>> We can agree that relabeling can be abused, but it does not stand to
>> reason that labeling (i.e. the correct, unchanged label) has no role in
>> tuple patterns. Again, it serves as documentation for the pattern, just as
>> labels serve as documentation for tuples, enum cases, and functions. There
>> are many languages that see no reason for labels at all, but Swift is not
>> one of those languages.
>>
>>
>>>
>>>
>>>> ~Robert Widmann
>>>>
>>>> On May 5, 2017, at 12:53 AM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>>>
>>>> Ah, I see from your proposed grammar update: you're proposing to
>>>> prohibit the use of labels entirely in a tuple pattern.
>>>>
>>>> This is much more than just prohibiting tuple shuffling, and I'm rather
>>>> disappointed that you described such a dramatic change using a corner case.
>>>> There are very good reasons why someone finds 'let (y: x, x: y) = (x: 1, y:
>>>> 2)' confusing and would support its removal, but it is entirely another
>>>> ballgame to remove labels from tuple patterns altogether.
>>>>
>>>>
>>>> On Thu, May 4, 2017 at 23:47 Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>>>
>>>>> Now I'm confused. The ordinary meaning of the word "shuffle" is not
>>>>> changing but rather reordering, and all of your examples are of reordering.
>>>>>
>>>>> To be clear, are you proposing the prohibition of *adding or removing*
>>>>> labels as well? A previous discussion on tuple shuffling on this list saw
>>>>> consensus that assigning a value of type (label1: T, label2: U) to a
>>>>> variable of type (T, U) and vice versa should absolutely be supported,
>>>>> whether or not reordering is permitted.
>>>>>
>>>>> And how about *restating* existing labels without any adding or
>>>>> removing? To be clear:
>>>>>
>>>>> ```
>>>>> let (partialValue: v, overflow: o) = 42.addingReportingOverflow(42)
>>>>> ```
>>>>>
>>>>> ...involves absolutely no changes in labels whatsoever. The return
>>>>> type is (partialValue: Int, overflow: ArithmeticOverflow).
>>>>>
>>>>> Either one of these scenarios is commonly used, and it is astonishing
>>>>> to me that they would be eliminated.
>>>>>
>>>>> On Thu, May 4, 2017 at 23:28 Robert Widmann <devteam.codafi at gmail.com>
>>>>> wrote:
>>>>>
>>>>>> That doesn't involve a parameter *reordering*, but because it
>>>>>> changes argument labels it's a shuffle.
>>>>>>
>>>>>> ~Robert Widmann
>>>>>>
>>>>>> 2017/05/05 0:16、Xiaodi Wu <xiaodi.wu at gmail.com> のメッセージ:
>>>>>>
>>>>>> Robert,
>>>>>>
>>>>>> As I mentioned on Twitter, getting rid of tuple shuffles would not
>>>>>> cure your example, which does not involve a shuffle. Unless you're
>>>>>> proposing to disallow the use of labels during destructuring entirely,
>>>>>> which I would think to be very much unacceptable. Example:
>>>>>>
>>>>>> ```
>>>>>> let (partialValue: v, overflow: o) = 42.addingReportingOverflow(42)
>>>>>> ```
>>>>>>
>>>>>> This involves no shuffling and should absolutely remain allowed.
>>>>>>
>>>>>>
>>>>>> On Thu, May 4, 2017 at 21:15 Robert Widmann via swift-evolution <
>>>>>> swift-evolution at swift.org> wrote:
>>>>>>
>>>>>>> Hi all,
>>>>>>>
>>>>>>> So sorry that this proposal comes so late in the game, but I feel
>>>>>>> it’s too important not to bring it to the attention of the community now.
>>>>>>> Attached is a proposal to deprecate a language feature many of you will
>>>>>>> probably have never had the chance to use: Tuple Shuffles.  I’ve attached a
>>>>>>> copy of the first draft of the proposal below, but the latest copy can be
>>>>>>> read on Github
>>>>>>> <https://github.com/apple/swift-evolution/pull/705/files>.
>>>>>>>
>>>>>>> Thanks!
>>>>>>>
>>>>>>> ~Robert Widmann
>>>>>>>
>>>>>>> Deprecate Tuple Shuffles
>>>>>>>
>>>>>>>    - Proposal: SE-NNNN
>>>>>>>    <https://github.com/CodaFi/swift-evolution/blob/8eaf320b3c2a117909fc0269c398e89c033a4b9f/proposals/NNNN-filename.md>
>>>>>>>    - Authors: Robert Widmann <https://github.com/codafi>
>>>>>>>    - Review Manager: TBD
>>>>>>>    - Status: Awaiting review
>>>>>>>
>>>>>>>
>>>>>>> <https://github.com/CodaFi/swift-evolution/blob/8eaf320b3c2a117909fc0269c398e89c033a4b9f/proposals/NNNN-deprecate-tuple-shuffles.md#introduction>
>>>>>>> Introduction
>>>>>>>
>>>>>>> This proposal seeks the deprecation of a little-known feature of
>>>>>>> Swift called a "Tuple Shuffle".
>>>>>>>
>>>>>>> <https://github.com/CodaFi/swift-evolution/blob/8eaf320b3c2a117909fc0269c398e89c033a4b9f/proposals/NNNN-deprecate-tuple-shuffles.md#motivation>
>>>>>>> Motivation
>>>>>>>
>>>>>>> A tuple-shuffle is an undocumented feature of Swift in which one can
>>>>>>> re-order the indices of a tuple by writing a pattern that describes a
>>>>>>> permutation in a syntax reminiscent of adding type-annotations to a
>>>>>>> parameter list:
>>>>>>>
>>>>>>> let a = (x: 1, y: 2)var b: (y: Int, x: Int)
>>>>>>> b = a
>>>>>>>
>>>>>>> It can be used to simultaneously destructure and reorder a tuple:
>>>>>>>
>>>>>>> let tuple = (first: 0, second: (x: 1, y: 2))let (second: (x: b, y: c), first: a) = tuple
>>>>>>>
>>>>>>> It can also be used to map parameter labels out of order in a call
>>>>>>> expression:
>>>>>>>
>>>>>>> func foo(_ : (x : Int, y : Int)) {}foo((y: 5, x: 10)) // Valid
>>>>>>>
>>>>>>> Note that a tuple shuffle is distinct from a re-assignment through a
>>>>>>> tuple pattern. For example, this series of statements will continue to
>>>>>>> function as before:
>>>>>>>
>>>>>>> var x = 5var y = 10var z = 15
>>>>>>> (z, y, x) = (x, z, y)
>>>>>>>
>>>>>>> Their inclusion in the language complicates every part of the
>>>>>>> compiler stack, uses a syntax that can be confused for type
>>>>>>> annotations <https://twitter.com/CodaFi_/status/860246169854894081>,
>>>>>>> contradicts the goals of earlier SE's (see SE-0060
>>>>>>> <https://github.com/apple/swift-evolution/blob/9cf2685293108ea3efcbebb7ee6a8618b83d4a90/proposals/0060-defaulted-parameter-order.md>),
>>>>>>> and makes non-sensical patterns possible in surprising places.
>>>>>>>
>>>>>>> Take switch-statements, for example:
>>>>>>>
>>>>>>> switch ((0, 0), 0){ case (_ : let (y, z), _ : let s): () // We are forbidden from giving these patterns names other than "_" default: ()
>>>>>>> }
>>>>>>>
>>>>>>> This proposal seeks to deprecate them in Swift 3 compatibility mode
>>>>>>> and enforce that deprecation as a hard error in Swift 4 to facilitate their
>>>>>>> eventual removal from the language.
>>>>>>>
>>>>>>> <https://github.com/CodaFi/swift-evolution/blob/8eaf320b3c2a117909fc0269c398e89c033a4b9f/proposals/NNNN-deprecate-tuple-shuffles.md#proposed-solution>Proposed
>>>>>>> solution
>>>>>>>
>>>>>>> Construction of Tuple Shuffle Expressions will become a warning in
>>>>>>> Swift 3 compatibility mode and will be a hard-error in Swift 4.
>>>>>>>
>>>>>>> <https://github.com/CodaFi/swift-evolution/blob/8eaf320b3c2a117909fc0269c398e89c033a4b9f/proposals/NNNN-deprecate-tuple-shuffles.md#detailed-design>Detailed
>>>>>>> design
>>>>>>>
>>>>>>> In addition to the necessary diagnostics, the grammar will be
>>>>>>> ammended to simplify the following productions:
>>>>>>>
>>>>>>> tuple-pattern → (tuple-pattern-element-list <opt>)
>>>>>>> tuple-pattern-element-list → tuple-pattern-element | tuple-pattern-element , tuple-pattern-element-list- tuple-pattern-element → pattern | identifier:pattern+ tuple-pattern-element → pattern
>>>>>>>
>>>>>>>
>>>>>>> <https://github.com/CodaFi/swift-evolution/blob/8eaf320b3c2a117909fc0269c398e89c033a4b9f/proposals/NNNN-deprecate-tuple-shuffles.md#impact-on-existing-code>Impact
>>>>>>> on Existing Code
>>>>>>>
>>>>>>> Because very little code is intentionally using Tuple Shuffles,
>>>>>>> impact on existing code will be negligible but not non-zero.
>>>>>>>
>>>>>>> <https://github.com/CodaFi/swift-evolution/blob/8eaf320b3c2a117909fc0269c398e89c033a4b9f/proposals/NNNN-deprecate-tuple-shuffles.md#alternatives-considered>Alternatives
>>>>>>> considered
>>>>>>> Continue to keep the architecture in place to facilitate this
>>>>>>> feature.
>>>>>>> _______________________________________________
>>>>>>> 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/20170505/2f46d98b/attachment.html>


More information about the swift-evolution mailing list