Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Perl, how does the || operator work?

Tags:

perl

So here are the

$y = 0 | 2 | 4;  # answer is  6

$x = 0 || 2 || 4;  # answer is 2

I know why $y is 6 because it's using the OR operator on each number and 2 | 4 = 6 but for $x...

Why is it 2?

like image 522
K.T Avatar asked May 18 '11 23:05

K.T


4 Answers

Because 2 is the first non-falsy item and a logical OR short circuits. It evaluates zero which is false, then 2 which is not false so it is done and returns 2. Consider the output of the following example:

$val = 1;
sub a_proc {
    print "a_proc: ", $val++, "\n";
    1;
}
$another_val = &a_proc || &a_proc;

This will output a_proc: 1. As soon as a_proc returns a true value, the interpreter can stop evaluating since a logical OR of true and any value is true.

like image 147
D.Shawley Avatar answered Oct 18 '22 10:10

D.Shawley


Its a short-circuiting, value-preserving logical or. Basically, it evaluates each of the things between the || in turn, until it finds one that is not false, at which point it returns that one and doesn't evaluate any subsequent operands.

edit

There are two important features of perl's logical ops

  • they are short circuiting in that they evaluate the left operand first, and it if it is true (false for &&) do NOT evaluate the right operand

  • they are value preserving in that they convert the operand to a boolean true or false for the conjunction (and to determine whether to evaluate the right operand), but the result of the expression is the original value before the conversion to boolean

Both of these features are very important and they combine to make || particularly useful in perl -- much more so than in C/C++ where it is just short-circuiting and NOT value preserving.

like image 35
Chris Dodd Avatar answered Oct 18 '22 10:10

Chris Dodd


While the operators look similar, their purpose is actually different.

From perldoc perlop:

Binary "||" performs a short-circuit logical OR operation. That is, if the left operand is true, the right operand is not even evaluated.

Compared to:

Binary "|" returns its operands ORed together bit by bit.

The purpose of || is to come up with an answer to "is x || y true or false?", while the purpose of bitwise or - | - is to come up with a product (?) of operands, or something like "what is the result of x | y?"

Since the only interesting two results from || is true or false, the statement can (and is) short-circuted, thereby causing this effect.

In the first statement: (0 | 2) = 2, (2 | 4) = 6

In the second statement: (0 || 2) = 2, (2 || ...) = 2

Interestingly, bitwise or is setting boolean values inside a binary number. Adding a true or false value on the positions within the binary representation of the number.

0000 | 0010 = 0010
0010 | 0100 = 0110
0110 | 0001 = 0111
0111 | 0001 = 0111 # no change

Which is very handy for storing multiple boolean values in one number, which can be checked with the & (bitwise AND).

0101 & 0100 = 0100 (true)
0101 & 0010 = 0000 (false)

There are 10 kinds of people: Those who understand binary numbers, and those who don't.

like image 32
TLP Avatar answered Oct 18 '22 09:10

TLP


EXPR_A || EXPR_B

is more or less equivalent to

do { my $rv = EXPR_A; if ($rv) { $rv } else { EXPR_B } }

Or in English,

  1. First, it evalutes EXPR_A in scalar context.
  2. If value is true, this value is returned.
  3. If the value is false, EXPR_B is evaluated and returned.

Sometimes you'll see them chained.

EXPR_A || EXPR_B || EXPR_C || EXPR_D

is just

( ( EXPR_A || EXPR_B ) || EXPR_C ) || EXPR_D

so just apply the above recursively.

You end up with the result of the first expression that returns true, or the result of the last if none are true.

like image 37
ikegami Avatar answered Oct 18 '22 10:10

ikegami