Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Infix macro := reparsing the LHS?

4 views
Skip to first unread message

Audrey Tang

unread,
Apr 19, 2006, 10:08:29 AM4/19/06
to perl6-c...@perl.org
Not sure if this is p6l or p6c... Fallback to the latter. :)

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

signature.asc

Larry Wall

unread,
Apr 19, 2006, 12:50:49 PM4/19/06
to perl6-c...@perl.org
On Wed, Apr 19, 2006 at 10:08:29PM +0800, Audrey Tang wrote:
: Not sure if this is p6l or p6c... Fallback to the latter. :)

:
: 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?

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

Larry Wall

unread,
Apr 19, 2006, 2:43:57 PM4/19/06
to perl6-c...@perl.org
After some discussion on IRC, we have all declarators implying a signature
syntax, either with parens for full sig or without for a limited one arg
syntax:

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

0 new messages