Perl 为什么wantarray在调用foo()| | die时在标量上下文中返回?

Perl 为什么wantarray在调用foo()| | die时在标量上下文中返回?,perl,list,Perl,List,我刚刚花了很多时间调试了一个问题,这个问题可以追溯到wantarray()。我把它浓缩成这个测试用例。(忽略以下事实,$!在此场景中不会有任何有用的信息)。我想知道的是,为什么在第二个示例中,wantarray不认为它在列表上下文中被调用: #!/usr/bin/env perl use strict; use warnings; use Test::More; { my ( $one, $two ) = foo(); is( $one, 'a', 'just foo' );

我刚刚花了很多时间调试了一个问题,这个问题可以追溯到
wantarray()
。我把它浓缩成这个测试用例。(忽略以下事实,
$!
在此场景中不会有任何有用的信息)。我想知道的是,为什么在第二个示例中,
wantarray
不认为它在列表上下文中被调用:

#!/usr/bin/env perl

use strict;
use warnings;
use Test::More;

{
    my ( $one, $two ) = foo();
    is( $one, 'a', 'just foo' );
    is( $two, 'b', 'just foo' );
}

{
    my ( $one, $two ) = foo() || die $!;
    is( $one, 'a', '|| die' );
    is( $two, 'b', '|| die' );
}


done_testing();

sub foo {
    return wantarray ? ( 'a', 'b' ) : 'bar';
}
该测试的输出为:

$ prove -v wantarray.pl
wantarray.pl ..
ok 1 - just foo
ok 2 - just foo
not ok 3 - || die
not ok 4 - || die
1..4

#   Failed test '|| die'
#   at wantarray.pl line 15.
#          got: 'bar'
#     expected: 'a'

#   Failed test '|| die'
#   at wantarray.pl line 16.
#          got: undef
#     expected: 'b'
# Looks like you failed 2 tests of 4.
Dubious, test returned 2 (wstat 512, 0x200)
Failed 2/4 subtests

Test Summary Report
-------------------
wantarray.pl (Wstat: 512 Tests: 4 Failed: 2)
  Failed tests:  3-4
    Non-zero exit status: 2
    Files=1, Tests=4,  0 wallclock secs ( 0.03 usr  0.01 sys +  0.02 cusr  0.00 csys =  0.06 CPU)
    Result: FAIL
逻辑or(
|
)是标量运算符,因此使用它将强制
foo()
的计算成为标量上下文

试试这个:

my @a = 10 .. 100;
print(@a || 2), "\n";
# prints 91

如果不是因为数组是在标量上下文中求值的,您会希望它打印
@a
中的元素。

因为它不是在列表上下文中调用的
| |
将标量上下文置于其左侧,在本例中,其左侧是表达式
foo()

你应该改写

my ( $one, $two ) = foo() or die $!;

操作符的绑定比赋值操作符更松散,因此现在它的LHS是整个表达式
my($one,$two)=foo()
,而
foo
的上下文由列表赋值操作符决定,每个人都很高兴。

原因在于
操作符的优先级。您的语句基本上是这样解析的:

my ( $one, $two ) = ( foo() || die $! );
在本例中,
|
将其操作数放在标量上下文中


另一方面,如果您将
|
更改为优先级较低的
,您的测试将通过。

+1个写得很好的问题非常感谢。:)选择一个被接受的答案有点难,但是@hobbs提供的答案对我来说似乎更清楚一些。