doc icon indicating copy to clipboard operation
doc copied to clipboard

Clarify the rules for assigning/binding to multiple variables in a single declaration

Open codesections opened this issue 4 years ago • 1 comments

The docs currently use "destructuring assignment" as a synonym for "list assignment". For example, in the Item and List assignment section, we provide these examples

my $f;
($f,) = 7,8,9;                 # list assignment to List with one element 
say $f;                        # OUTPUT:  «7␤» 
say ( ($f,) ).VAR.^name;       # OUTPUT:  «List␤» 

# ATTENTION: special declaration syntax! 
my ($g) = 7,8,9;               # list assignment to List with one element 
say $g;                        # OUTPUT:  «7␤» 
say ( ($g) ).VAR.^name         # OUTPUT:  «List␤»

and then say that

The last two examples above are simple destructuring assignments that select the first item of the right-hand side list.

Conflating these two terms is understandable – as far as I can tell, most languages don't make this distinction (e.g., JavaScript calls both features destructuring assignment; PHP calls both features list assignment.

However, in Raku there is a distinction. As @jnthn pointed out in rakudo/rakudo/issues/4522:

At the heart of the issue is that the grammar parses a signature here; in the case we really do destructuring (my (:$numerator, :$denominator) := 4.2) then the signature is exactly what we want. While "destructuring" is often used loosely to describe things like my ($x, $y) = 1, 2, strictly this is an example of list assignment, not destructuring.

The case given in the issue here is not destructuring either; there's no binding operator, and I think for attributes there cannot be. Rather, the situation here is that we are declaring a list of attributes, just as my ($x, $y); is declaring a list of lexical variables. In this case, the signature should "decay" into just declarations (and in the case of my ($x, $y) = 1, 2, we expect it to also produce a list of the declared variables; what happens from there is also list assignment rather than destructuring).

Apparently this issue has been confusing people for a while – it came up in the 2017 Review of Perl 6 post:

I don’t understand the logic of making a syntactic distinction between list assignment and full destructuring assignment — and silently flattening the lefthand list structure in the first case — but there you have it.

And I'll admit that it's not a distinction I'd really focused on until it came up in the context of that Rakudo issue. I think I now understand the distinction and will prepare a PR – but I'll be especially looking for feedback on it to be sure I don't misstate anything.

codesections avatar Sep 13 '21 19:09 codesections

As the change I just made to this issue's title implies, I no longer think that the heart of this issue relates to "destructuring assignment" – in fact, I've come around to the view that "destructuring assignment" isn't that clear of a term in Raku.

Instead, I think this is really about clarifying the rules for binding/rebinding variables (which are much more consistently enforced post rakudo/rakudo#4536) and then explaining the consequences those rules have when declaring multiple variables. I recently wrote up the rebinding rules (as I understand them) for a StackOverflow answer. Here's the key part:

The rules for rebinding are:

  • Sigilless "variables" cannot be rebound (and can't be reassigned, so they aren't really "variables")
  • Variables with a sigil generally can be rebound, subject to the exception below.
  • If a sigiled variable is part of a Signature, then it cannot be rebound unless it is declared to be rebindable via the is copy or is rw traits.
    • This applies to a function's Signature (thus sub f($a) { $a := 42 } is illegal)
    • It also applies to Signatures that are destructured as part of variable declaration with :=. E.g., in my ($var1, $var2) := ('foo', 'bar'), the right-hand side is a Signature and thus $var1 and $var2 cannot be rebound.

Between that and the info in the rakudo/rakudo#4536 thread, I think we have all the info we need to clear this up in the docs. Now it's just a matter of one of us finding the time to actually do so!

codesections avatar Feb 11 '22 22:02 codesections