Perlでは、手動で0にundefを変換する優雅な方法は何ですか?
質問
私はこのフォームでフラグメントを持っています:
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;
以上の2つの変数が懸念しているので、現実は、もっと厄介です。
私が本当に書きたいことはこれです:
my $total = $some_href->{$code}{'A'} + $some_href->{$code}{'B'};
とundefを正しく0と評価されるが、私はほとんどすべての実行でこれらの警告を取得しています:
Use of uninitialized value in addition (+) at Stats.pm line 192.
これらのメッセージが離れて行くようにする最良の方法は何でしょうか。
NB:私は厳格な使用 'とそれが関連だ場合は、「警告を使用して」
。解決
それはあなたがstrict
とwarnings
を使用していることを良いことです。警告の目的は、Perlは意図しない(したがって正しくない)である可能性が高いの行動を見ていると、警告を発することです。あなたが意図的にそれをやっているときは、ローカルに警告を無効にするには完全に罰金です。 undef
は、数値コンテキストで0
として扱われます。あなたは両方の未定義の値を有し、かつ、それらがゼロに評価持つ大丈夫なら、単に警告を無効にします:
my $total;
{
no warnings 'uninitialized';
$total = $some_href->{$code}{A} + $some_href->{$code}{B};
}
注:あなたがする必要がある唯一の警告を無効にして、最小の範囲で行うことができます。
あなたが警告を無効に嫌うなら、、他のオプションがあります。 5.10のとして、あなたはデフォルト値を設定する//
(定義されて-OR)演算子を使用することができます。その人の前に、多くの場合、||
(論理OR)を使用しますが、それはfalseと評価値のために間違ったことを行うことができます。 Perlのの前の5.10のバージョンではデフォルト値に堅牢な方法は、彼らがdefined
しているかどうかを確認することです。
$x = $y // 42; # 5.10+
$x = $y || 42; # < 5.10 (fragile)
$x = defined $y ? $y : 42; # < 5.10 (robust)
他のヒント
あなたは第二のために、「初期化されていない」の警告をオフにすることができます:
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
しかし私には非常に良い見ていません。
あなたがそれらを追加していると、ちょうどundefsををフィルタリングます。
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');
my $a = $some_href->{$code}{'A'} || 0;
my $b = $some_href->{$code}{'B'} || 0;
my $total = $a + $b;
この場合、それが原因であなたのフォールバック値のfalseの値に未定義の値と同じに扱うためにOKです。