http://www.perlmonks.org?node_id=1017801

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 (Archbishop) 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 (Canon) 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 (Patriarch) 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.