11

さかのぼって問題をデバッグするのにかなりの時間を費やしましたwantarray()。私はそれをこのテストケースに落とし込みました。$!(このシナリオでは有用な情報がないという事実を無視してください)。私が知りたいwantarrayのは、2 番目の例で 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';
}

このテストの出力は次のとおりです。

$ 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
4

3 に答える 3

9

リストコンテキストで呼び出されていないためです。||は左辺にスカラー コンテキストを課します。この場合の左辺は式foo()です。

代わりに書くべきです

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

演算子はor代入演算子よりもさらに緩くバインドするため、その LHS は式全体my ($one, $two) = foo()になり、fooのコンテキストはリスト代入演算子によって決定され、誰もが満足します。

于 2013-07-08T21:41:33.387 に答える
6

その理由は、||演算子の優先度によるものです。あなたのステートメントは基本的に次のように解析されます。

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

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

一方、優先順位がはるかに低い に変更||するとor、テストは成功します。

于 2013-07-08T21:42:06.363 に答える
4

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

これを試して:

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

@a配列がスカラーコンテキストで評価されているため、そうでない場合は、要素が出力されると予想されます。

于 2013-07-08T21:40:41.733 に答える