2016-01-13 54 views
1

我最近遇到一个错误,use warnings FATAL ...编译指示将来自其他地方的静音警告解释为死亡原因。使用关于整个项目的警告同样的政策致命未初始化警告 - 在远处采取行动

use strict; 
# In one file: 

no warnings; 
my %hash; 
Foo->bar(my $temp = $hash{ +undef }); # this lives 
Foo->bar($hash{ +undef }); # this dies 

# Elsewhere 

package Foo; 
use warnings FATAL => qw(uninitialized); 

sub bar { 
    my ($self, $param) = @_; # prefectly safe 
    $param = "(undef)" 
     unless defined $param; # even safer 
    print "Param: $param\n"; 
} 

现在,这当然可以固定大的时候:考虑下面的示例。或者可以通过排除特定位置的undefs来解决这个问题(参见# this lives一行)。

我的问题是Foo包是否有一个可接受的解决方案,它不需要改变调用它的任何东西,以及这是否真的是Perl本身的错误。

回答

2

这不是一个错误。您正在经历一项功能的副作用,该功能可防止传递给subs的散列元素的不必要的自动化。


Perl通过引用传递。这意味着对函数中参数的更改将改变外部参数。

$ perl -E' 
    sub f { $_[0] = "xyz"; } 
    f($x); 
    say $x; 
' 
xyz 

这也适用于散列元素。

$ perl -E' 
    sub f { $_[0] = "xyz"; } 
    my %h; 
    f($h{x}); 
    say $h{x}; 
' 
xyz 

子不知道哈希任何事情,所以进入前子的存在被什么东西给它分配的哈希元素必须创建。

...还是这样做?如果元素不存在,f($h{x})始终会创建$h{x}通常是不合意的。因此,Perl推迟进行哈希查找,直到访问$_[0],此时知道该元素是否需要生动化。这就是为什么警告来自于子内部。

特别是,当你调用f($h{x}) Perl不通过$h{x}给分。取而代之的是,它通过同时包含到%h基准和密钥值(x)神奇标量。这会推迟做哈希查找,直到$_[0]被访问,在那里它被称为$_[0]是否使用地方分配与否。

  • 如果$_[0]的方式,其中它不改变(即,如果它是用作一个rvalue),散列元件被抬起,而不生机就使用它。

  • 如果$_[0]以其可以改变的方式被使用(即,如果它被用作左值),则散列元素被生动化并返回。

$ perl -E' 
    sub f { my $x = $_[0]; } # $_[0] returns undef without vivifying $h{x} 
    sub g { $_[0] = "xyz"; } # $_[0] vivifies and returns $h{x} 
    my %h; 
    f($h{x}); 
    say 0+keys(%h); 
    g($h{x}); 
    say 0+keys(%h); 
' 
0 
1 
+0

难以置信。至少现在开始有意义了...... – Dallaylaen

相关问题