2013-07-08 44 views
11

我剛剛花了一大堆時間來調試我追溯到wantarray()的問題。我已經完成了這個測試案例。 (忽略$!在這種情況下不會有任何有用的信息)。我想知道的是爲什麼wantarray不認爲它被稱爲在列表環境在第二個例子:爲什麼在調用foo()||時,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 
+1

+1寫得好的問題 –

回答

9

因爲它不在列表上下文中調用。 ||在其左側施加了標量上下文,其左側在這種情況下是表達式foo()

你應該寫,而不是

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

or運營商結合更加鬆散比賦值運算符,所以現在它的LHS是整個表達式my ($one, $two) = foo(),並foo的上下文由列表賦值運算符確定,每個人都很開心。

4

邏輯或(||)是一個標量運算符,因此使用它將迫使foo()的評估成爲標量上下文。

試試這個:

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

你會想到這個打印元素@a如果不是因爲陣列已在標量環境進行了評估。

6

原因是由於||運營商的優先權。您的發言基本分析是這樣的:

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

||把操作數在標量上下文在這種情況下。

另一方面,如果您將||更改爲or(優先級低得多),您的測試將通過。

+0

非常感謝。 :)選擇一個被接受的答案是一種折騰,但@hobbs提供的答案似乎對我來說更加清晰。 – oalders

相關問題