2016-01-13 62 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