In this line:
[Dog ::T $ ($x) where 1, *$, *@] := moose();
the left hand side is probably not a valid Perl 6 expression, yet
according to the current spec, it needs to be parsed implicitly as if a
:() is around it.
How does this work in practice? Is an infix macro allowed to change the
"is parsed" of its LHS? Should that trigger a reparse, or do we use
(potentially costly) prescanning?
A way out of this may be requiring :() on the LHS of :=, and treat it as
an infix macro that only changes how the RHS is parsed (which would be
trivial). Or, for symmetry, make := ordinary infix, and require both
side to be :() and \() respectively.
I agree that
($x, $y) := ($y, $x)
is clean (and featured in various places). However, as long as there
are some Signature forms that isn't valid expression form, or would
triggered parse-time expression-form macros that wouldn't trigger in
Signature forms, I can't figure out how it would work.
The infix:<=> has no such problem because all valid lvalue expressions
are also valid rvalue expressions in Perl 6.
Thanks,
Audrey
From S06:
(This means, for instance, that an infix
operator can change the parse rules for its right operand but not
its left operand.)
: A way out of this may be requiring :() on the LHS of :=, and treat it as
: an infix macro that only changes how the RHS is parsed (which would be
: trivial). Or, for symmetry, make := ordinary infix, and require both
: side to be :() and \() respectively.
That seems excessive, since we don't require people to \ their ordinary
argument lists. There's a sense in which all = and := thingies are just
postfix list metaoperators. That is
($x, $y) = ($y, $x)
is more like
\($x,$y).assign($y,$x);
And we could drive that list operator-ness as far as to make the right side
of = or := a list, so that you could get away with
($x, $y) = $y, $x
as pugs currently allow for
my ($x, $y) = $y, $x
I dislike that inconsistency, but we could make it consistent either
way. (For the rest of the discussion I'll assume that := parses like a
listop, that is, with a different precedence leftward than rightward.)
: I agree that
:
: ($x, $y) := ($y, $x)
:
: is clean (and featured in various places). However, as long as there
: are some Signature forms that isn't valid expression form, or would
: triggered parse-time expression-form macros that wouldn't trigger in
: Signature forms, I can't figure out how it would work.
Could we say that :() is required if there is anything in the signature besides
a list of variables? Or we could go one step further and say that anything
that parses correctly as an rvalue but can be trivially transformed into a
signature is allowed, which gives us *@rest and maybe a few other things.
Another approach would be to deem that (Type starts a signature,
but that may be too unclean and/or not general enough.
: The infix:<=> has no such problem because all valid lvalue expressions
: are also valid rvalue expressions in Perl 6.
If assignment to a signature binds (a big "if" given human factors),
then we could just say you have to put the colon in either place:
:($x, $y) = $y, $x
($x, $y) := $y, $x
But the conservative thing to say right now is that you this is guaranteed
to work:
:($x, $y) := $y, $x
We can always relax it later. Once again, we see that ASCII just doesn't
have enough brackets, or we could say something like
⦇$x, $y⦈ := $y, $x
❲$x, $y❳ := $y, $x
⟦$x, $y⟧ := $y, $x
⦅$x, $y⦆ := $y, $x
and then we don't feel like we're being redundant.
Oh, another thing we haven't really settled is whether Sig ~~ Cap actually
binds the variables in Sig or just tells you whether they *would* bind.
Or equivalently, just binds them vacuously over a null scope, suggesting
that it could be adverbed with a block thus:
Sig ~~ Cap :{...}
Cap ~~ Sig :{...}
making those equivalent to:
-> Sig {...}.Cap
But I know if I start thinking about switches now my head will explode:
given Sig { when Cap :{...} {...} }
given Cap { when Sig :{...} {...} }
especially if anyone suggests that
given Sig { when Cap {...} }
given Cap { when Sig {...} }
should implicitly bind over the scope of the inner block.
Larry
my Int $x = 1;
my (Int $x where Odd, Dog $spot = fido()) := (1,$lassie);
The sigil or the parens still control the context of the right side in
the case of assignment, but the listop form of either = or := causes the
right side to parse as a list argument that doesn't need parens, just as
with ordinary list operators. The scalar form is unaffected, so
loop($a = 1, $b = 2; ; $a++, $b++) {...}
still works.
In the case of
my ($a, $b, $c) = 1,2,3;
the left side is parsed as a signature and "degrades" to an ordinary lvalue
list, but since "my" already restricts what can occur in such a list, that's fine.
If you wish to bind to a signature without a declarator, you have to use
the colon form of sig:
:($a,$b,$c) := 1,2,3;
Assignment to a sig does binding but maintains copy semantics so that
my $a = $b;
my ($a,$c) = $b,$d;
do not alias, and
:($a,$b) = $b,$a
swaps values rather than clobbering one of them, because the binding is to
temp copies.
my $a, $b, $c;
is still an error, generally caught by the fact that $b hasn't been declared.
I'm sure I've left out something important...
Larry