2008-11-04 62 views
7

下面是一些简单的Perl来计算数组中出现值的次数。这运行没有任何警告。Perl何时自动初始化变量?

use warnings; 
use strict; 

my @data = qw(1 1 2 3 4 5 5 5 9); 
my %histogram; 
foreach (@data) 
{ 
    $histogram{$_}++; 
} 

当循环体改为

$histogram{$_} = $histogram{$_} + 1; 

Perl中警告说, “除了未初始化值的使用”。

这是怎么回事?为什么当作为操作数提供给++运算符并且未使用+运算符初始化时,初始化该值?

回答

14

+运算符评估左边的表单和右边的表单,然后返回两者的总和。散列调用评估没有看到任何特殊的上下文。

++运算符时有一些特殊的魔法建在从perlop中手册页引用,关于++运算符:

“民主基金”始终被视为数字,尤其是前改变为0递增(这样undef值的后增量将返回0而不是“undef”)。

编辑:要阐述的区别,++改变地方的价值,而只是+采用它的参数作为输入。当+看到未定义的值时,通常出现了问题,但对于++,您的散列操作示例非常典型 - 用户希望将undef视为0,而不必每次都检查和初始化。因此,以这种方式对待这些运营商似乎是有道理的。

7

这不是Perl必须初始化值,但它并不总是警告他们。不要试图为此考虑一条规则,因为你总是会发现异常,而当你认为你已经发现异常时,下一个版本的Perl将改变你的警告。

在这种情况下,正如Harleqin所说,自动增量算子有一个特例。

0

正如布赖恩所说:它仍然如此,它只是警告你。警告会告诉您某些您可能无意使用的效果的操作。

您具体要求要求的值为$histogram{$_},将值加1,然后将其分配给同一个槽。这是我不希望对自动激活这里的工作方式相同:

my $hash_ref = $hash_for{$key_level_1}; 
$hash_ref->{$key_level_2} = $value; 

因为它在这里:

$hash_for{$key_level_1}{$key_level_2} = $value; 

魔术可能不会像优化工作。优化编译器会注意到a = a + 1a++是一样的,所以在汇编语言中有一个增量操作符时,它可以使用该优化指令而不是假装它需要保留第一个值,然后覆盖它,因为它不是实际上并不需要。

为了提高每次运行的性能,优化是额外审查和开销一次。但是,动态语言并不能保证你不会以相同的速度增加开销,否则你会试图减少开销。

+0

尽管警告不会直接破坏构建,但应该注意它们。 – Svante 2008-11-04 12:57:02

7

某些操作员故意省略“未初始化”警告,以方便您使用 ,因为它们通常用于左侧或唯一操作数的0或“”默认值有意义的情况。

它们是:++和 - (或者pre或post),+ =, - =,。=,| =,^ =,& & =,|| =。

请注意,其中一些错误地在使用绑定变量时发出警告:请参阅http://perl5.git.perl.org/perl.git/blob/HEAD:/t/op/assignwarn.t中标记为TODO的测试。