So here are the
$y = 0 | 2 | 4; # answer is 6
$x = 0 || 2 || 4; # answer is 2
我知道为什么$y
是6
,因为它在每个数字上使用OR
运算符,2 | 4 = 6
,但对于$x
...
为什么是2
?
So here are the
$y = 0 | 2 | 4; # answer is 6
$x = 0 || 2 || 4; # answer is 2
我知道为什么$y
是6
,因为它在每个数字上使用OR
运算符,2 | 4 = 6
,但对于$x
...
为什么是2
?
因为2是第一个非假值,逻辑或运算符会停止计算。它会先判断0,发现是假值,然后判断2,发现不是假值,所以直接返回了2。考虑以下示例的输出:
$val = 1;
sub a_proc {
print "a_proc: ", $val++, "\n";
1;
}
$another_val = &a_proc || &a_proc;
这将输出a_proc: 1
。只要a_proc
返回真值,解释器就可以停止评估,因为true
和任何值的逻辑或操作结果都是true
。
(0 || 2) || 4
?这意味着它实际上进行了两次计算,但短路了第二次。 - TLP||
被评估,但只有最左侧的||
的右侧被评估。1)评估0||2
。2)评估0
。3)评估2
。4)由于“短路”,即左侧的0 || 2
返回true,因此不会评估4
。 - ikegami||
进行比较时,Perl 不会向前查找并说:“好的,该行的其余部分只有更多的 ||
比较,我可以在这里进行短路计算。” 它实际上识别和评估第二个 ||
,然后相应地进行短路运算。这样,一个真值就可以“贯穿”整个 ||
语句链,但链本身不被短路运算。 - TLP||
连接在一起时会发生什么。Perl 是否将整个语句链识别为一个并立即短路,还是始终通过它们所有(始终只检查 LHS)。我知道这是一个相当无用的知识,但我很好奇。 - TLP||
之间的每个内容,直到找到一个不为假的内容,然后返回该内容并且不评估任何后续操作数。它们是短路的,因为它们首先评估左操作数,如果它为真(对于&&
为假),则不评估右操作数。
它们是保值的,因为它们将操作数转换为布尔值来进行合取(and用于确定是否评估右操作数),但表达式的结果是转换为布尔值之前的原始值。
||
在Perl中特别有用——比在C/C++中更加实用,那里只是短路而不是保值。(0 | 2) = 2, (2 | 4) = 6
在第二个语句中:(0 || 2) = 2, (2 || ...) = 2
有趣的是,按位或
是在二进制数内设置布尔值。将 true 或 false 值添加到数字的二进制表示中的位置。0000 | 0010 = 0010
0010 | 0100 = 0110
0110 | 0001 = 0111
0111 | 0001 = 0111 # no change
这对于在一个数字中存储多个布尔值非常方便,可以使用&
(按位与
)进行检查。
0101 & 0100 = 0100 (true)
0101 & 0010 = 0000 (false)
有十种人:懂二进制的和不懂二进制的。
EXPR_A || EXPR_B
更或多或少等同于
do { my $rv = EXPR_A; if ($rv) { $rv } else { EXPR_B } }
或者用英文表述:
有时你会看到它们被链接在一起。
EXPR_A || EXPR_B || EXPR_C || EXPR_D
只是
( ( EXPR_A || EXPR_B ) || EXPR_C ) || EXPR_D
所以只需递归应用上述方法。
最终得到第一个返回 true 的表达式的结果,如果没有表达式返回 true,则得到最后一个表达式的结果。