2013-07-08 1 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()です。

あなたは今そのLHSは、式全体my ($one, $two) = foo()あり、そしてfooのコンテキストは、リスト代入演算子により決定され、代わりに

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

orオペレータがさらに緩く代入演算子よりも結合し記述する必要があり、誰もが幸せです。

4
論理

または(||)はスカラー演算子なので、これを使用すると、foo()の評価がスカラーコンテキストになります。

はこれを試してみてください:

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

あなたは配列をスカラーコンテキストで評価されているので、それがなかった場合、これは@aの要素を印刷するように期待したいです。

6

理由は、||演算子の優先順位によるものです。あなたの文は基本的に次のように解析されます。

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

||は、この場合、スカラーコンテキストでそのオペランドを置きます。

一方、優先度がはるかに低い||orに変更すると、テストは合格になります。

+0

ありがとうございました。 :)それは受け入れられた答えを選ぶために投げたものでしたが、@hobbsが提供したものは私にとってははっきりしているようです。 – oalders

関連する問題