Update “tuple” handling – Alternative “2-way” version of #1560#1608
Update “tuple” handling – Alternative “2-way” version of #1560#1608jskeet merged 3 commits intodotnet:draft-v8from
Conversation
This replaces the 3-way division of tuples & deconstructing; into *tuple_literal*, *deconstructing_assignment* and *local_deconstructing_declaration*; with a 2-way division; into *tuple_literal* and *deconstructing_assignment*. The distinction between deconstruction assigning to *existing* vs. *new* variables is not syntactical in this version, even though C# distinguishes the two cases. Instead a textual list of restrictions is provided which govern what a *deconstructor* can contain based on its position within the code. Other changes since dotnet#1560 include: - Renamed abridged_* rules per suggestion. - Inclusion of *declaration_expression* as an option in a *for_initializer* (this was an accidental omission in dotnet#1560). This topic is not yet complete: deconstructing foreach, which was missing in v7, is not yet included. This will either be added in an update to this PR, or as a new PR building on this one.
BillWagner
left a comment
There was a problem hiding this comment.
This is great @Nigel-Ecma
I had a few small questions / nits in text to consider. One may even be just the result of my failing eyesight.
standard/expressions.md
Outdated
| The result of the deconstruction is the *tuple-literal* formed from the values returned via the out parameters of a call to `E.Deconstruct(...)`. The result is semantically equivalent to replacing `E` with the following pseudo-code: | ||
|
|
||
| >```csharp | ||
| > E.Deconstruct(out T1 v1, ..., out TN vn) andThen (v1, ..., vn); | ||
| >``` | ||
|
|
||
| Where `andThen` is a pseudo C# operation which performs its left-hand operand and then returns its right-operand as the result. | ||
| <!-- markdownlint-disable MD028 --> | ||
|
|
||
| <!-- markdownlint-enable MD028 --> | ||
| >> *Note*: `andThen` is the equivalent of C & C++’s comma operator. *end note* |
There was a problem hiding this comment.
I think we want all these lines to be indented, as they are part of the bullet item on 1272. (I apologize if they already are, that's just hard are to see.
There was a problem hiding this comment.
Correct the bullet on 1272 is a multi-paragraph one and also contains one code and one note “display”. They mostly look correctly indented to me, the exception being the Note on 1284 which GitHub is showing with the wrong indentation and two left side bars. My editor shows the Note correctly indented (i.e. indented the same as the code E.Deconstruct…), but to achieve that I had to insert a double >> which seems logically wrong… But then what is logical about markdown markup… 😉
I think we need a GitHub markdown whisperer on this one, @RexJaeschke or @jskeet can either of you suggest the required incantation?
standard/expressions.md
Outdated
| > *Note*: ANTLR grammar semantics enforce this requirement due to the ordering of the alternatives. *Semantically* there is no overlap between the four alternatives, this is a syntactic disambiguation. | ||
|
|
||
| The `+=` and `-=` operators with an event access expression as the left operand are called the ***event assignment operator***s. No other assignment operator is valid with an event access as the left operand. The event assignment operators are described in [§12.23.5](expressions.md#12235-event-assignment). | ||
| The *simple_assignment* and *compound_assignment* expressions assign a new value to a variable, a property, or an indexer element. Event assignment ([§12.23.5](expressions.md#12235-event-assignment)), a subset of *compound_assignment*, assigns a new value to an event. The *ref_assignment* expression assigns a variable reference ([§9.5](variables.md#95-variable-references)) to a reference variable ([§9.7](variables.md#97-reference-variables-and-returns)). The *deconstructing_assignment* assigns new values to one or more *variable_reference*s. |
There was a problem hiding this comment.
nit: Would deconstructing_assignment require "two or more variable_references?
There was a problem hiding this comment.
No, but we’re both wrong! There are two errors in the line:
- It is zero or more – a deconstructor can contain only discards (
_) (and nested deconstructors with only discards…). Thinking two as you did makes sense, tuples must have at least two elements, why I wrote one for the 3-way I cannot remember offhand but I’m “sure” there was a good reason that applies in the 3-way case… 😉 - The line hasn’t been changed from the 3-way where it does indeed assign “new values” to existing variables (or variable_references). However in the 2-way it can also declare new variables and assign them initial values…
The next commit will contain:
The simple_assignment and compound_assignment expressions assign a new value to a variable, a property, or an indexer element. Event assignment (§12.23.5), a subset of compound_assignment, assigns a new value to an event. The ref_assignment expression assigns a variable reference (§9.5) to a reference variable (§9.7). The deconstructing_assignment assigns values to zero or more variable_references.
This is only an overview para so I skipped the distinction between existing and newly declared variables, that is already covered in the full text.
standard/expressions.md
Outdated
| > *Note*: An expression of type `dynamic` cannot be deconstructed. *end note* | ||
| - Otherwise if there is a unique instance or extension method `S.Deconstruct`; with `n ≥ 2` output parameters, with types `T₁` to `Tₙ`, and no other parameters; then `E` can be deconstructed. | ||
|
|
||
| The result of the deconstruction is the *tuple-literal* formed from the values returned via the out parameters of a call to `E.Deconstruct(...)`. The result is semantically equivalent to replacing `E` with the following pseudo-code: |
There was a problem hiding this comment.
As per email, I think this is where it would be good to re-emphasize in the first sentence that this is effectively a source-to-source transform. That would mitigate my concerns around using tuple-literal.
There was a problem hiding this comment.
The clause has been edited in the next commit, the changes are not large but hopefully sufficient.
jskeet
left a comment
There was a problem hiding this comment.
Various comments and a few typo fixes (which I'm sure Nigel only left in so that I could feel useful) but I hope we're able to merge this in our meeting, creating follow-up issues for minor formatting and examples.
| <!-- markdownlint-disable MD028 --> | ||
|
|
||
| <!-- markdownlint-enable MD028 --> | ||
| >> *Note*: `andThen` is equivalent to C & C++’s comma operator. *end note* |
There was a problem hiding this comment.
This still looks weird in GitHub, but I'd propose that we don't block this PR on it. (We can file a new issue and fix it separately. We'll need to see what it looks like in Word too.)
There was a problem hiding this comment.
I'll file an issue tomorrow.
| - **is not** at the start of a statement, or | ||
| - **is** at the start of a statement and contains no *declaration_expression* | ||
|
|
||
| For these restrictions: |
There was a problem hiding this comment.
I think we should have a follow-up PR with examples of these restrictions. We can file an issue for that before merging this PR.
There was a problem hiding this comment.
I'll file an issue in the morning.
Co-authored-by: Jon Skeet <skeet@pobox.com>
jskeet
left a comment
There was a problem hiding this comment.
After discussion, we'll make this ready to review, and merge it. We'll file follow-up issues for:
- deconstructing foreach
- assignment (simple or deconstructing) to discards - search for "zero or more"
- examples of deconstructing assignment restrictions
- markdown handling of nested notes
|
Merging despite the failing test, which is about our tools rather than the standard. |
Fixes: #1155
Replaces: PR #1366, #1538, #1570
Alternative to: #1560
This replaces #PR1560’s 3-way division of tuples & deconstruction; into tuple_literal, deconstructing_assignment and local_deconstructing_declaration; with a 2-way division; into tuple_literal and deconstructing_assignment.
The distinction between a deconstruction assigning to existing vs. new variables is not syntactic in this version. Instead a textual list of restrictions is specified which; by governing what a deconstructor can contain based on its position within the code; distinguish the two cases.
Other changes since PR1560 include:
This topic is not yet complete: The deconstructing foreach stattement, which was missing in v7, is not yet included. This will either be added in an update to this PR, or as a new PR building on this one. For this reason this PR is marked as draft.