8

私はこの形の断片を持っています:

my $a = $some_href->{$code}{'A'}; # a number or undef
my $b = $some_href->{$code}{'B'}; # a number or undef
$a = 0 unless defined($a);
$b = 0 unless defined($b);
my $total = $a + $b;

3つ以上の変数が関係しているため、現実はさらに厄介です。

私が本当に書きたいのはこれです:

my $total = $some_href->{$code}{'A'} + $some_href->{$code}{'B'};

undefは正しく0と評価されますが、ほとんどすべての実行で次の警告が表示されます。

Use of uninitialized value in addition (+) at Stats.pm line 192.

これらのメッセージを消すための最良の方法は何ですか?

注意:関連する場合は、「厳密に使用」および「警告を使用」します。

4

4 に答える 4

16

strictとを使用しているのは良いことですwarnings。警告の目的は、Perlが意図的ではない(したがって正しくない)動作を検出したときに警告することです。意図的に行う場合は、ローカルで警告を無効にすることはまったく問題ありません。数値コンテキストのundef場合と同様に扱われます。0未定義の値とゼロと評価される値の両方に問題がない場合は、警告を無効にするだけです。

my $total;
{
  no warnings 'uninitialized';
  $total = $some_href->{$code}{A} + $some_href->{$code}{B};
}

注:必要な警告のみを無効にし、可能な限り最小の範囲で無効にしてください。

警告を無効にすることを嫌う場合は、他のオプションがあります。Perl 5.10以降では、//(defined-or)演算子を使用してデフォルト値を設定できます。それ以前は、人々はしばしば||(論理和)を使用しますが、それは偽と評価される値に対して間違ったことをする可能性があります。5.10より前のバージョンのPerlでデフォルト値を設定するための堅牢な方法は、それらがであるかどうかを確認することですdefined

$x = $y // 42;             # 5.10+
$x = $y || 42;             # < 5.10 (fragile)
$x = defined $y ? $y : 42; # < 5.10 (robust)
于 2009-08-29T14:03:41.527 に答える
6

「初期化されていない」警告を1秒間オフにすることができます。

my $a;
my $b = 1;
{
    no warnings 'uninitialized';
    my $c = $a+$b; # no warning
}
my $c = $a+$b; # warning

または、ゼロに短絡することもできます。

my $d = ($a||0)+$b; # no warning

しかし、私にはあまり見栄えがしません。

于 2009-08-29T10:45:22.203 に答える
4

それらを追加するときに、undefを除外するだけです。

use List::Util 'sum';

my $total = sum (0, grep {defined} $some_href->{$code}{'A'}, $some_href->{$code}{'B'});

あるいは

use List::Util 'sum';

my $total = sum (0, grep {defined} map {$some_href->{$code}{$_}} 'A', 'B');
于 2009-08-29T11:11:34.540 に答える
4
my $a = $some_href->{$code}{'A'} || 0;
my $b = $some_href->{$code}{'B'} || 0;
my $total = $a + $b;

この場合、フォールバック値があるため、false値を未定義値と同じように扱うことができます。

于 2009-08-29T13:48:10.063 に答える