[swift-evolution] [Proposal][Discussion] Deprecate Tuple Shuffles
Xiaodi Wu
xiaodi.wu at gmail.com
Fri May 5 02:27:23 CDT 2017
On Fri, May 5, 2017 at 2:14 AM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
> On Fri, May 5, 2017 at 1:44 AM, Robert Widmann <devteam.codafi at gmail.com>
> wrote:
>
>> I can see where you’re coming from, absolutely. I don’t intend to remove
>> necessary semantic content labels can provide if I don’t have to.
>>
>> For the sake of expediency - and because even with labels you can
>> destructure into a label-less pattern, I’ll concede this point and remove
>> the section about removing labeled patterns from the draft on Github.
>>
>
> Without that chunk, I would be fine with the proposal. It removes a clever
> part of the language, but perhaps too clever and now rather unexpected,
> with the direction in which it's evolving.
>
I should add, there's an added benefit here. If you allow labels but remove
shuffling, there's a good chance that *unintentional* shuffles get called
out during migration. Boom, bugs fixed, better code. Swift saves the day.
>
>> ~Robert Widmann
>>
>> On May 5, 2017, at 2:35 AM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>
>> 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/37cf8cea/attachment.html>
More information about the swift-evolution
mailing list