2016-01-06 53 views
7

爲什麼下面的代碼:關於不一致的行爲「不能用一個未定義的值作爲數組引用」

use strict; 
use warnings; 
no warnings 'uninitialized'; 

use Data::Dumper; 

my $user; 
my @data = @{$user->{ENTERPRISE}}; # Error on this line 
print Dumper($user), qq{Done!\n}; 

拋出錯誤「Can't use an undefined value as an ARRAY reference」,而下面的代碼:

use strict; 
use warnings; 
no warnings 'uninitialized'; 

use Data::Dumper; 

my $user; 
foreach my $enterprise(@{$user->{ENTERPRISES}}) { 
    print qq{Enterprise:}, $enterprise; 
} 
print Dumper($user), qq{Done!\n}; 

不扔東西,而是返回:

$VAR1 = { 
      'ENTERPRISES' => [] 
     }; 
Done! 

雙方都有問題的鱈魚在他們中,但只有一個正在拋出錯誤。

可能的答案:Perl's autovivification?

我在這裏在正確的軌道上?感謝您的輸入。

+1

你究竟在做什麼?事實上,你已經關閉了警告,這應該是一個非常好的警告,它不是一個好主意。 – Sobrique

+0

我只是想弄清楚Perl在一個地方拋出錯誤而不是在另一個地方拋出相同的代碼。第一個代碼塊來自舊代碼,拋出錯誤,必須修復,而第二個代碼塊是更新的代碼,我擔心也需要修復,但我猜並不是因爲它沒有拋出我看到的錯誤以往。 – Morrowind789

回答

9

是的,在第二種情況下發生的事情稱爲autovivification,它只發生在第二種情況下,因爲autovivification只發生在左值[1]

所以

@{ $x } = $y; 

意味着

@{ $x //= [] } = $y; 

$y = @{ $x }; 

並不意味着

$y = @{ $x //= [] }; 

請記住,foreach會將其循環變量替換爲迭代列表中的每個元素,因此這些元素將被評估爲左值。

自動生效記錄在perlref中,您可以通過autovivification編譯指示控制自動生效。


  1. 如果最終deferencing後跟一個索引(例如->[]->{}),參考表達本身被評估爲一個左值即使索引整體不。這意味着即使$y = @{ $x };不會,$y = $x->[0];$y = ${ $x }[0];也可以自動生效$x
+0

這是非常豐富的。關於foreach如何工作的最後一點是假設循環變量導致我們處於左值狀態,這真的會清除一些事情。左值/右值區分是否正式記錄在某處? – Morrowind789

+0

@ Morrowind789它在['perldoc perlref']中簡要提及(http://perldoc.perl.org/perlref。html#Using-References)在「使用引用」下的第3點。同樣在[perlglossary](http://perldoc.perl.org/perlglossary.html#autovivification)中的autovivification的定義下。 – ThisSuitIsBlackNot

+0

autovivication的文檔(在[perlref](http://perldoc.perl.org/perlref.html))確實:「這是我們前面提到的一種情況,其中引用可能會在左值情況下[...]這個過程被稱爲autovivification。「 – ikegami