我花了很多时间来调试我追溯到的问题wantarray().我把它提炼到这个测试用例.(忽略$!在这种情况下没有任何有用信息的事实).我想知道的是为什么wantarray不认为它在第二个例子中的LIST上下文中被调用:
#!/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';
}
Run Code Online (Sandbox Code Playgroud)
该测试的输出是:
$ 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
Run Code Online (Sandbox Code Playgroud)
因为它没有在列表上下文中调用.||在左侧施加标量上下文,在这种情况下它的左侧是表达式foo().
你应该写
my ( $one, $two ) = foo() or die $!;
Run Code Online (Sandbox Code Playgroud)
该or运营商的优先级比赋值运算符更加松散,所以现在它的LHS是整个表达式my ($one, $two) = foo(),和foo的情况下,通过列表赋值运算符确定,大家都高兴.
原因是||运营商的优先权.您的语句基本上解析如下:
my ( $one, $two ) = ( foo() || die $! );
Run Code Online (Sandbox Code Playgroud)
在||这种情况下把它的操作数的标量上下文.
另一方面,如果更改||为or优先级低得多,则测试将通过.