Perl: the Markov chain saw PerlMonks

### Why Perl boolean expression sometimes treated as lvalue?

by vsespb (Chaplain)
 on Feb 08, 2013 at 11:28 UTC Need Help??
vsespb has asked for the wisdom of the Perl Monks concerning the following question:

In continue of this http://www.perlmonks.org/?node_id=1017390 discussion
my \$a = 1; my \$b = 2; \$a && \$b = 3;
this does not work. good. but this
use strict; use warnings; sub a { \$_[0] = 3; } my \$x = 0; my \$y = 5; a(\$x && \$y); print "\$x\n";
prints 3 (because \$x aliased as 1-st arg to subrouting), so \$x && \$y works as lvalue. I wonder why so ? I didn't find documentation for this (not in perlsub/perlop)

Replies are listed 'Best First'.
Re: Why Perl boolean expression sometimes treated as lvalue?
by Athanasius (Chancellor) on Feb 08, 2013 at 12:24 UTC

In Perl, arguments are passed by reference, not by value. This is what perlsub means when it says: “The array @_ is a local array, but its elements are aliases for the actual scalar parameters.”

The subroutine call a(\$x && \$y) causes the Perl interpreter to evaluate the boolean expression \$x && \$y to determine which variable is to be aliased. If \$x is false, the expression short-circuits, so a reference to \$x is passed in to the sub; but if \$x is true, short-circuiting does not occur, and so it is a reference to \$y that is passed in to the sub.

So it is misleading to say that the boolean expression works as an l-value. Within sub a, the boolean expression is never seen — only the reference to either \$x or \$y — and it is this reference which works as an l-value.

I haven’t found anything in the documentation to explain the process by which Perl derives a reference (“alias”) from a complex expression given as an argument to a subroutine. It might be useful to know — but, in general, it’s safer and clearer to keep things simple and just pass a variable or a value.

Hope that helps,

 Athanasius <°(((>< contra mundum Iustus alius egestas vitae, eros Piratica,

perlop perlop perlop , precedence is everything :)

\$ perl -E " print ( 1 && 2 ) 2 \$ perl -E " sub ff { ++\$_[0] } my(\$f,\$a)=(1,5); ff( \$f && \$a ); say \$f +; say \$a; " 1 6
Re: Why Perl boolean expression sometimes treated as lvalue?
by tobyink (Abbot) on Feb 08, 2013 at 13:28 UTC

Hmmm... interesting disparity. The following may be of interest...

use v5.10; my (\$a, \$b) = (0, 0); sub lv :lvalue { \$_[0] } lv(\$a || \$b) = 2; lv(\$a && \$b) = 1; say \$a; say \$b;
package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: Why Perl boolean expression sometimes treated as lvalue?
by vsespb (Chaplain) on Feb 08, 2013 at 12:22 UTC
Well, seems this example makes more sense.
my \$a = 0; my \$b = 2; my \$z = \(\$a && \$b); \$\$z = 4; print \$a;
(prints 4)

Interesting ... note the parens, perl parses it correctly

\$ perl -MO=Deparse,-p -le " \$a= 1 && 2; print \$a; " BEGIN { \$/ = "\n"; \$\ = "\n"; } (\$a = 2); print(\$a); -e syntax OK \$ perl -MO=Deparse,-p -e " \$a && \$b = 3; " Can't modify logical and (&&) in scalar assignment at -e line 1, near +"3;" -e had compilation errors. ((\$a && \$b) = 3);

But there is no code to execute this :) its default Can't modify %s http://perl5.git.perl.org/perl.git/blob?f=op.c#l2020

2012 /* FALL THROUGH */ 2013 default: 2014 nomod: 2015 if (flags & OP_LVALUE_NO_CROAK) return NULL; 2016 /* grep, foreach, subcalls, refgen */ 2017 if (type == OP_GREPSTART || type == OP_ENTERSUB 2018 || type == OP_REFGEN || type == OP_LEAVESUBLV) 2019 break; 2020 yyerror(Perl_form(aTHX_ "Can't modify %s in %s", 2021 (o->op_type == OP_NULL && (o->op_flags & OPf +_SPECIAL) 2022 ? "do block" 2023 : (o->op_type == OP_ENTERSUB 2024 ? "non-lvalue subroutine call" 2025 : OP_DESC(o))), 2026 type ? PL_op_desc[type] : "local"));
Re: Why Perl boolean expression sometimes treated as lvalue?
by ikegami (Pope) on Feb 11, 2013 at 04:31 UTC

Quite simply:

• \$y always returns the scalar, not a copy of it.
• && always returns the scalar its LHS returned or the scalar(s) its RHS returned, not a copy of it.

That's it. Why isn't it documented that they don't make a copy in rvalue context? Why would it.

If you wanted to explicitly copy the scalar, you could do a( 0+( \$x && \$y ) ). Then, \$_[0] = 3; will modify the anonymous scalar the addition constructed.

You're missing the point

If so, your message does not help. Please clarify the question if you think I didn't understand it.

Create A New User
Node Status?
node history
Node Type: perlquestion [id://1017801]
Approved by vinoth.ree
Front-paged by RMGir
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (6)
As of 2017-08-17 10:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
Who is your favorite scientist and why?

Results (286 votes). Check out past polls.

Notices?