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

gube has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks,

I usually use the 'or' operator and zero value while assigning values to scalar, when i assign scalar varaible to scalar variable. (For Eg. my $var = $var1 || 0). So, if $var1 is empty the 0 will be assign to $var variable. In this subroutine also i did the same. But, in this case if i print "$price" the output i am getting is 8. Anyone please guide me. I can return 0,0 from the subroutine. By mistake i did 'or' opearator and assign zero value. I just wanted to know how the values assigning.

#!/usr/local/bin/perl use strict; use warnings; my ($price, $floor) = &get_price_floor() || 0; print $price; sub get_price_floor { return (10, 8); }

Replies are listed 'Best First'.
Re: In What basis the subroutine return values assign to variables ?
by bart (Canon) on Jul 30, 2007 at 10:40 UTC
    my ($price, $floor) = &get_price_floor() || 0;
    The || you attached to the end of this statement forces the sub to work in scalar context.
    return (10, 8);
    in scalar context is using the comma operator (familiar from in C, if you know C), hence, it'll calculate each term in turn, and return the value of the last expression, and that is 8. That explains the result you're getting.

    Now, as for an alternative... I assume in case of error get_price_floor is supposed to return an empty list, no? Then, you could try:

    my ($price, $floor); ## needs to be declared in a separate statement ($price, $floor) = &get_price_floor() or ($price, $floor) = (0, 0);
    Note that or has a lower precedence than the assignment =.
    Here, the first assignment happens in list context, so the code will work, but the or will look at the assignment in scalar context, and it'll see a false if you assign an empty list, a true if it's a non-empty list. So the assignment on the right hand side will only happen if the one on the left hand side assigned an empty list.

    Test:

    sub good { return (10, 8); } sub bad { return (); } my ($price, $floor); ($price, $floor) = good() or ($price, $floor) = (0, 0); print "good: price=$price, floor=$floor\n"; ($price, $floor) = bad() or ($price, $floor) = (0, 0); print "bad: price=$price, floor=$floor\n";
    Result:
    good: price=10, floor=8 bad: price=0, floor=0

    p.s. please don't use & to prefix your subroutines for no good reason. We regulars think it's ugly. You're not supposed to care if a word is a built-in or a sub. A module can easily override many of the built-ins, so even if you think you know wich is a built-in and which is a sub, you may be wrong — and it doesn't matter.

Re: In What basis the subroutine return values assign to variables ?
by FunkyMonk (Chancellor) on Jul 30, 2007 at 10:38 UTC
    || is causing get_price_floor() to be evaluated in scalar context. A list eg (10, 8), when evaluated in scalar context, returns the last element, 8. That's what's assigned to $price, while $floor is left undefined.

    Simple solution: get rid of || 0

    BTW, do you know what & does to a subroutine call? If you don't (and I don't believe you do), don't use it. Just call your subroutine without it:

    my ($price, $floor) = get_price_floor();
Re: In What basis the subroutine return values assign to variables ?
by Anno (Deacon) on Jul 30, 2007 at 10:45 UTC
    The or-trick can't be used with multiple (list-) assignments. The code
    my ($price, $floor) = get_price_floor() || 0; sub get_price_floor { return (10, 8); }
    is parsed as
    my ($price, $floor) = (get_price_floor() || 0);
    which means that get_price_floor() is called in scalar context. Consequently, the return statement happens in scalar context which means that (10, 8) evaluates to 8 (the scalar comma operator). That is assigned to $price while $floor comes out undefined.

    Since you have defined get_price_floor() yourself, it isn't quite clear why you want to prepare for the case it doesn't return anything -- you *know* what it returns. If you have to do that, one way would be the not particularly attractive

    my ($price, $floor); (($price, $floor) = get_price_floor()) || (($price, $floor) = ( 0, 0));
    Also note I have removed the ampersand from the calls to get_price_floor(). It isn't necessary and, in fact, has side effects you normally don't want.

    Anno

Re: In What basis the subroutine return values assign to variables ?
by gube (Parson) on Jul 30, 2007 at 11:39 UTC
    Thanks guys..I understood very well. Hereafter, i will not use "&" while calling subroutines. Thank you so much.