what is ||= in perl for?

12,763

Solution 1

$sheet -> {MaxRow} ||= $sheet -> {MinRow};

is equivalent to:

$sheet -> {MaxRow} = ( $sheet -> {MaxRow} || $sheet -> {MinRow});

The local OR operator evaluates the second operand only if the first one is false. So, the MaxRow will get the value of the MinRow if MaxRow is 0 (possibly the first iteration).

Solution 2

The ||= operator is logical-OR-assign. It's similar to +=, which is add-assign. It computes the logical OR of the LHS and RHS, and then assigns the result to the LHS, which therefore must be a valid lvalue.

In other words, just as

$a += 3;

is equivalent to

$a = $a+3;

we can say that

$a ||= 1;

is equivalent to

$a = $a||1;

Now, with regard to the statement you referred to in your question, there's slightly more going on there than in my example above. In your statement, the LHS is not just a simple variable token, but is a variable token that is being treated as a hash reference ($sheet) and is being dereferenced to get the value that is keyed with the string 'MaxRow'. The RHS is also a hash dereference operation on $sheet, but whose key is 'MinRow'. But the behavior is the same; we can say that

$sheet->{'MaxRow'} ||= $sheet->{'MinRow'};

is equivalent to

$sheet->{'MaxRow'} = $sheet->{'MaxRow'}||$sheet->{'MinRow'};

(Note: I always like to explicitly quote hash key values as strings, because that's what they are, but not everyone goes for that degree of explicitness.)

For more about the logical OR operation, see http://en.wikipedia.org/wiki/Logical_disjunction, and for Perl-specific info, see http://perldoc.perl.org/perlop.html#C-style-Logical-Or (for || and //) and http://perldoc.perl.org/perlop.html#Logical-or-and-Exclusive-Or (for or). Most relevant quote, from the Perl documentation on ||:

Binary "||" performs a short-circuit logical OR operation. That is, if the left operand is true, the right operand is not even evaluated. Scalar or list context propagates down to the right operand if it is evaluated.

That doesn't quite fully explain it; in the case that the LHS evaluates to a truthy value (see below for definition), then the return value of the || operation is the value of the LHS, otherwise it is the value of the RHS.

In Perl, logical values are generally represented by 0 (or sometimes '' or undef) for false and 1 for true. However, to be more specific, any value that is not one of the above three false values is treated as true, and sometimes programmers refer to this distinction using the informal terms "truthy" and "falsy". IOW, 0, '', and undef are falsy, and everything else is truthy. See http://www.perlmonks.org/?node=what%20is%20true%20and%20false%20in%20Perl%3F for more detail.

Share:
12,763

Related videos on Youtube

Bostwick
Author by

Bostwick

I'm a developer with an EE degree who at one point was an optical engineer.

Updated on June 28, 2022

Comments

  • Bostwick
    Bostwick almost 2 years

    Looking at the documentation for Reading Excel, there is a statement I don't really understand.

    Can someone explain what $sheet -> {MaxRow} ||= $sheet -> {MinRow}; does ?

    I get that its an assignment operator. However I don't understand how || is meant to work ?

  • felwithe
    felwithe over 6 years
    Is there a version of this that evaluates the right hand side first? I'm looking for a shortcut that means $a = $b if $b.
  • bgoldst
    bgoldst over 6 years
    @felwithe It depends on what you want to happen to $a in the case that the RHS conditional evaluates to falsy. If you want $a's existing value to be retained, then your assignment statement works as-is, since the infix if operator works as you wrote it, and will prevent the assignment from taking place at all if its conditional is falsy. If you want a "default" value like undef, then I think the answer to your question is technically no, but you can write a subroutine to do it: sub if2 { return $_[1] ? $_[0] : undef; }, and then to call it: $a = if2 $b, $b;.
  • felwithe
    felwithe over 6 years
    Hi-- I mean just like it says. I just thought maybe there was a nifty Perl shortcut that I didn't know about.