用'||'评估语句 在Perl

waw*_*awa 3 perl

有人可以解释一下这里发生了什么吗?

我尽可能地简化了.

( 1 || 2 == 1 )     is TRUE (as expected)
( 1 || 2 == 2 )     is TRUE (as expected)
Run Code Online (Sandbox Code Playgroud)

我也希望以下两者都是正确的(但这可能表明缺乏理解......)

( 1 == ( 1 || 2 ) ) is TRUE  
( 2 == ( 1 || 2 ) ) is FALSE <--- !!! I don't understand this..
Run Code Online (Sandbox Code Playgroud)

现在它开始有点奇怪......

( 2 == 1 || 2 )     is TRUE  
( 3 == 1 || 2 )     is TRUE  <--- !!! I don't understand this..
Run Code Online (Sandbox Code Playgroud)

经过一番戏剧之后,我发现以下内容:

( 1 == ( 1 || 2 ) ) is FALSE
( 2 == ( 1 || 2 ) ) is TRUE

( 1 == ( 1 && 2 ) ) is TRUE
( 2 == ( 1 && 2 ) ) is FALSE
Run Code Online (Sandbox Code Playgroud)

您可能猜测我正在尝试按照以下方式执行某些操作:

sub foo {
    # ... blah blah ...
    return 0 if $status == ( 2 || 4 || 7 || 9);
    # ... do other stuff ...
    return 1;
}

my $result = foo();
if ($result) { 
    # then do something based on a result
    } else {
    # log failure or whatever
}
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用这个成语,但额外的"$ status"似乎是多余的:

return 0 if ( $status == 1 || $status == 4 || $status == 7 ); # and so on...
Run Code Online (Sandbox Code Playgroud)

我也知道我可以使用正则表达式替换或检查值是否在允许值的数组中.

但是我想明白为什么这不像我期望的那样.

mob*_*mob 10

$status == ( 2 || 4 || 7 || 9)
Run Code Online (Sandbox Code Playgroud)

不会做你期望的.(如果它确实做了你所期望的,你认为$status == (2 && 4 && 7 && 9)应该是什么意思?)该陈述相当于

$status == 2
Run Code Online (Sandbox Code Playgroud)

||并且&&二进制运算符,它总是返回其标量操作数之一.将它们视为等效于这些二元函数可能有所帮助:

sub OR {
    my ($a,$b) = @_;
    if ($a) {
        return $a;
    } else {
        return $b;
    }
}

sub AND {
    my ($a,$b) = @_;
    if ($a) {
        return $b;
    } else {
        return $a;
    }
}
Run Code Online (Sandbox Code Playgroud)

(我掩饰的短路特性||&&,但是这不是那么重要了这个职位).

注意到==的优先级高于||&&,我们可以重写来讲所有你的表情ANDOR:

( 1 || 2 == 1 )     -->   (OR(1,2==1))  --->  OR(1,0) --> 1  TRUE
( 1 || 2 == 2 )     -->   (OR(1,2==2))  --->  OR(1,1) --> 1  TRUE
Run Code Online (Sandbox Code Playgroud)

这两个表达式都是正确的,但不是因为你期望的原因.

( 1 == ( 1 || 2 ) ) -->   (1 == OR(1,2))   --->   (1==1) TRUE
( 2 == ( 1 || 2 ) ) -->   (2 == OR(1,2))   --->   (2==1) FALSE


( 2 == 1 || 2 )     -->   OR(2==1,2)   --->  OR(0,2) -->  2  TRUE  
( 3 == 1 || 2 )     -->   OR(3==1,2)   --->  OR(0,3) -->  3  TRUE


( 1 == ( 1 || 2 ) ) -->   (1==OR(1,2)) --->  (1==1)  TRUE, not FALSE
( 2 == ( 1 || 2 ) ) -->   (2==OR(1,2)) --->  (2==1)  FALSE, not TRUE

( 1 == ( 1 && 2 ) ) -->   (1==AND(1,2)) ---> (1==1) TRUE
( 2 == ( 1 && 2 ) ) -->   (2==AND(1,2)) ---> (2==1) FALSE
Run Code Online (Sandbox Code Playgroud)

而你最初的检查想法

$status == ( 2 || 4 || 7 || 9)
Run Code Online (Sandbox Code Playgroud)

相当于

$status == OR(OR(OR(2,4),7),9)
$status == OR(OR(2,7),9)
$status == OR(2,9)
$status == 2
Run Code Online (Sandbox Code Playgroud)


zou*_*oul 5

( 2 == ( 1 || 2 ) ) is FALSE <--- !!! I don't understand this..
Run Code Online (Sandbox Code Playgroud)

||运营商将返回它遇到的第一个"真"值或假.因此,1||2评估为1和数字比较2失败.至于你的代码,你可以使用Perl6 :: Junction:

if ($status == any(1, 4, 7)) {
    ...
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*oss 5

||操作者只需像你想的不工作(希望?)它.你可以通过打印出一些表达式的结果来看到这一点.

$ perl -E'say 1 || 2' # 1
$ perl -E'say 2 || 1' # 2
Run Code Online (Sandbox Code Playgroud)

操作员很懒惰.它只评估操作数,直到它知道结果是什么.

两种方式实现你想要的.

1 /创建包含您感兴趣的值的哈希.

my %good_status = map { $_ => 1 } qw[2 4 7 9];
return if $good_status{$status};
Run Code Online (Sandbox Code Playgroud)

2 /使用List :: MoreUtils中any函数.

use List::Utils 'any';
return if any { $status == $_ } qw[2 4 7 9];
Run Code Online (Sandbox Code Playgroud)


Too*_*mai 5

||语句不能以您尝试使用它的方式使用.在英语中说"如果1是1或2"是有意义的,但是在大多数(如果不是所有编程语言)中你必须说"如果1是1或1是2"(即,1 == 1 || 1 == 2或者其中的某个宏).

什么是实际发生的情况是,||&&,对两个数字时,正在评估他们找到的第一个非零值.所以1 || 6 -> 1虽然6 || 1 -> 6.结合==正在评估第一,如果没有括号都参与其中,这导致:

( 1 || 2 == 1 ) -> (1) == 1 -> true
( 1 || 2 == 2 ) -> (1) == 2 -> false

( 1 == ( 1 || 2 ) ) -> 1 == (1) -> true
( 2 == ( 1 || 2 ) ) -> 2 == (1) -> false

( 2 == 1 || 2 ) -> false || 2 -> 2 -> true
( 3 == 1 || 2 ) -> false || 2 -> 2 -> true

( 1 == ( 1 || 2 ) ) -> 1 == (1) -> true
( 2 == ( 1 || 2 ) ) -> 2 == (1) -> false

( 1 == ( 1 && 2 ) ) -> 1 == (1) -> true
( 2 == ( 1 && 2 ) ) -> 2 == (1) -> false
Run Code Online (Sandbox Code Playgroud)