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.
|