Syntax understanding problem

R

Rainer Weikusat

Ben Morrow said:
This is incorrect. In an expression such as

($a = 23) + 1

the parenthesised part is not a list, it is a scalar.

It is a kind of term, an expression in parentheses, and it will be
interpreted based on its context. The +-operator enforces a scalar
context for both of its operands. But the result of

($a = 23) + 1

is really the same as the result of

($b = 24, $a = 23) + 1

Grammatically (5.10.1),

term : termbinop

[...]

| '(' expr ')'
{ $$ = sawparens(IF_MAD(newUNOP(OP_NULL,0,$2), $2));
TOKEN_GETMAD($1,$$,'(');
TOKEN_GETMAD($3,$$,')');
}

expr : expr ANDOP expr

[...]


| argexpr %prec PREC_LOW


/* Expressions are a list of terms joined by commas */
argexpr : argexpr ','

which is the 5.10.1 'list production'.
 
J

Justin C

It might be easier to understand this when knowing the implementation:
Internally, a list is represented as an OP_LIST (corresponding with
pp_list) whose arguments are the elements of the list (Except when the
list is an argument list for another list operator. In this case, the
OP_LIST/ pp_list is elided).

I don't know what OP_LIST and pp_list mean. I've googled and
nothing becomes clearer.


Justin.
 
R

Rainer Weikusat

Justin C said:
[...]
It might be easier to understand this when knowing the implementation:
Internally, a list is represented as an OP_LIST (corresponding with
pp_list) whose arguments are the elements of the list (Except when the
list is an argument list for another list operator. In this case, the
OP_LIST/ pp_list is elided).

I don't know what OP_LIST and pp_list mean. I've googled and
nothing becomes clearer.

As Ben already wrote, these are terms from the Perl source code. The
second of the text was intended to be the more important part. A list as
it appears in some Perl source code,

/^something/ and $a = 1, $b = 2;

is translated to a function call,

/^something/ and list($a = 1, $b = 1);

list is an internal function which looks like this (except that it is
really implemented in C and manipulates the Perl stack directly)

sub list
{
return wantarray() ? @_ : $_[$#_];
}

IOW, the comma-separated terms in a 'free hand list' are really nothing
but comma-separated terms appearing in the argument list of a function
call and behave in the same way: They are all evaluated and produce a
value (if they produce a value, eg, a 'next' would cause a control
transfer instead) and the (internal) list function processes these
values (Sort of. It returns them unchanged in list context and returns
its last argument in scalar context).
 
T

Tim McDaniel

Back in January 2014 said:
Quoth (e-mail address removed):

Yes, an assignment whose LHS is explicitly parenthesised is always a
list assignment.

A little more on lists and assignments.

There was a discussion at work that touched on the difference between
"array" and "list". There was an assertion along the lines of "lists
*do not exist* in scalar context". In composing a reply, including
why I don't agree with that mental model, I tried this (lots of
extraneous stuff there from previous versions):

$ perl -e 'sub foo {13} sub bar { 14 } sub baz { @a = (5,6,7); @a }; (1 ? $x : @y) = (foo(), bar(), baz()); print $x, "\n"'

I was hoping that it would show that the list on the right could be
evaluated either in a scalar or a list context. But the parens needed
around the ?: operator made it a list LHS, so the RHS was evaluated in
a list context, so it prints

13

just as if I'd written "($x) = (13, 14, 5, 6, 6);".

Only after I rechecked "man perlop" did I realize that ?: has higher
precedence than =, so the parens weren't necessary.

$ perl -e 'sub baz { @a = (5,6,7); @a }; 0 ? $x : @y = (13, 14, baz()); print "x=$x", ", y=", join(" ", @y), "\n"'
x=, y=13 14 5 6 7
$ perl -e 'sub baz { @a = (5,6,7); @a }; 1 ? $x : @y = (13, 14, baz()); print "x=$x", ", y=", join(" ", @y), "\n"'
x=3, y=

But then I tried with a variable, in a test program

sub baz { my @a = (5,6,7); @a };
foreach (0, 1) {
$_ ? $x : @y = (13, 14, baz());
print "x=$x", ", y=", join(" ", @y), "\n";
}
exit 0;

I got the error
Assignment to both a list and a scalar at local/test/117.pl line 3, near ");"
Apparently 1?: and 0?: did compile-time constant folding and avoided
the problem.

The ": lvalue" attribute for a sub only allows a SCALAR lvalue, so
I can't bury the conditional in a sub.

So I don't know of any way to write
... something ... = (13, 14, 5, 6, 7);
in Perl so that it doesn't know at compile time whether the right-hand
side is in a scalar or list context.

But
sub foo {
return (1, 2, 5, 3);
}
doesn't know from just that code what the context is, so I think this
sub is enough of an example that it's not so useful to say "lists do
not exist in scalar context": I aver that it's better to think that
there's a list there, and in a scalar context it is evaluated to its
last element.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,093
Messages
2,570,607
Members
47,227
Latest member
bluerose1

Latest Threads

Top