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;

现实更加混乱,因为涉及两个以上的变量。

我真正想写的是:

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

使用strictand很好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

您可以关闭“未初始化”警告一秒钟:

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
my $a = $some_href->{$code}{'A'} || 0;
my $b = $some_href->{$code}{'B'} || 0;
my $total = $a + $b;

在这种情况下,由于您的后备值,可以将错误值视为与未定义值相同的值。

于 2009-08-29T13:48:10.063 回答
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 回答