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
?
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
.
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.
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.
EXPR_A || EXPR_B
is more or less equivalent to
do { my $rv = EXPR_A; if ($rv) { $rv } else { EXPR_B } }
Or in English,
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With