Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Why Perl boolean expression sometimes treated as lvalue?

by vsespb (Chaplain)
on Feb 08, 2013 at 11:28 UTC ( [id://1017801]=perlquestion: print w/replies, xml ) 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 (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.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1017801]
Approved by vinoth.ree
Front-paged by RMGir
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (2)
As of 2024-03-19 05:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found