2009-08-29 23 views
8

我在这个形式的片段:在Perl中,有没有优雅的方式将undef手动转换为0?

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'}; 

,并民主基金正确地评价为0,但我几乎在每次运行得到这些警告:

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

什么是最好的方法,使这些消息消失了?

注意:如果相关,我'严格使用'和'使用警告'。

+0

它是相关的。在这种情况下,您启用了您不关心的警告。 – jrockway 2009-08-29 15:14:28

回答

16

这很好,你正在使用strictwarnings。警告的目的是在Perl看到可能是无意的(因此不正确)行为时提醒您。当你故意这样做时,在本地禁用警告是完全正确的。在数字上下文中将undef视为0。如果你没事既具有未定义的值,并让他们评估为零,只是禁用警告:

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

注:仅禁用你需要的警告,并在最小的范围可能这样做。

如果您不愿意禁用警告,还有其他选项。从Perl 5.10开始,您可以使用//(defined-or)运算符来设置默认值。在此之前,人们经常使用||(逻辑或),但对于评估为错误的值,可以做出错误的事情。 Perl 5.10以前版本中默认值的可靠方法是检查它们是否为defined

$x = $y // 42;    # 5.10+ 
$x = $y || 42;    # < 5.10 (fragile) 
$x = defined $y ? $y : 42; # < 5.10 (robust) 
+3

是的,“$ y || 42”是脆弱的,但“$ y || 0”并不十分脆弱。 – innaM 2009-08-29 17:14:06

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 

不看对我很好,虽然。

4

当你添加它们时,只要过滤掉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'); 
4
my $a = $some_href->{$code}{'A'} || 0; 
my $b = $some_href->{$code}{'B'} || 0; 
my $total = $a + $b; 

在这种情况下,这是确定治疗,因为你的回退值的相同不定值假值。

+1

这段代码并不完全一样。它也将空字符串,一个定义的值,变为0.这可能不是你想要的。 – 2009-08-29 21:12:02

+0

我以为他在添加它们时,实际上是他想要的。 – 2009-08-30 02:34:58

相关问题