2016-12-30 5 views
2

私は次のコードを持っている:

Can't use an undefined value as a HASH reference at ...

しかし、同様のコードがエラーを生成しません:私は、私はエラーを取得する some_subを呼び出すと

$headers; 
some_sub(%$headers); 

$headers->{ x }; 

なぜdoesnの」最初の例でも2番目の例と同じようにautovivificationが動作しますか?

UPD

私は@ThisSuitIsBlackNotによって指摘。私は実際に尋ねる:

why my $h; $h->{foo} works and my $h; %$h doesn't

UPD
実際のコード:サブに渡されたとき

my $email = Email::Simple->create(() 
    ,header => [() 
     ,To    => $address 
     ,From   => $cnf->{ from } 
     ,Subject  => $subject 
     ,'Content-Type' => 'text/html; charset="utf8"' 
     ,%$headers 
    ] 
    ,body => $body 
); 
+0

まあ、エラーメッセージが何を言っていますか? 'HASH参照として未定義の値を使用することはできません...'それはどういう意味ですか?それは '$ headers'について何を伝えますか? –

+1

そのコードは完成していますか?もしそうなら、 '$ headers'はその値として' undef'を持ち、あなたが参照していない 'hash'を逆参照することはできません。あなたは 'use strict;最低限、警告を使用してください。あなたは 'my $ headers = {};を考慮することもできます。 'perl autovivification'のような用語であなたの検索は何を返しましたか?私はGoogleを使い、Wikipedia、Perl Maven、Perl Monksに従うのに役立ついくつかの探している記事を手に入れました。そのうち、[Explaining Autovivification](http://www.perlmonks.org/?node_id=691557)が最も適切と思われます。 –

+3

そのエラーは発生しません。あなたは完全な例を提供できますか? – Schwern

答えて

4

更新  なぜコードが自動化されないのかが説明されています。

サブは、匿名配列を要素として持つ–と%$headersがその配列に埋め込まれたリスト(ハッシュ)をとります。 アノン配列 であるため、%$headersを変更する必要はありません。したがって、自動化は行われず、定義されていない参照に対して逆参照が試行されるため、以下で説明する致命的な実行時エラーが発生します。


左辺値コンテキストに使用%$ref autovivifies。これは、サブコールで発生する可能性があります。下記を参照してください。

表示されるエラーは、未定義の参照の使用によるものです。例えば、ステートメント

my %hash = %{ $ref }; 

試みは$refに記憶された記憶場所からハッシュをコピーし、%hashに割り当てます。 %hashはコンパイル時に作成されますが、$refにハッシュが見つからない場合、または$refに何もない場合はエラーが発生します。オートバイ化はここでは起こりません。evalが、それは "初期化されていない値" についての警告を表示し

perl -wE'use strict; my $h; my %h = eval { %$h }; say $h; say "hi"' 

ことを、生き残るために-edときに有効にuse strict

perl -wE'use strict; my $h; my %h = %$h; say $h' 

では、これは致命的なランタイムエラー

 
Can't use an undefined value as a HASH reference at -e line 1. 

をスローします空白行を入力し、次にhiを入力します。ハッシュはありません。

しかし、サブルーチンに引数として使用される場合、これは警告やエラーなし、ラインHASH(0x257cd48)を印刷するように、それは

perl -wE'use strict; sub tt { 1 }; my $h; tt(%$h); say $h' 

をautovivifies呼び出します。

逆参照オブジェクトが左辺コンテキストで使用されている場合、自動化が行われます。つまり、変更可能にする必要があります。サブルーチン呼び出しでは、関数への引数は@_にエイリアスされているため、それらを変更する必要があります。同じエイリアシングの必要性は、foreachループで発生し、keysはハッシュイテレータをリセットします。 this postおよびthis postおよびthis postを参照してください。

説明とリンクのためにThisSuitIsBlackNotのおかげで

%$refは、無名配列の要素として渡されるため、別名にはなりません(arrayref自体は)。だから、自動化は始まりません。あなたはそのエラーを受け取ります。 perlglossary

In Perl, storage locations (lvalues) spontaneously generate themselves as needed, including the creation of any hard reference values to point to the next level of storage. The assignment $a[5][5][5][5][5] = "quintet" potentially creates five scalar storage locations, plus four references (in the first four scalar locations) pointing to four new anonymous arrays (to hold the last four scalar locations). But the point of autovivification is that you don’t have to worry about it.

からautovivification


も参照して、例えば、article from Effective Pearler

+2

実際には、 '%$ foo' *はl値のコンテキストで使用された場合、自動起動をトリガします:' perl -Mstrict -MDevel :: Peek -wE'my $ h; 1、%$ h;ダンプ$ h ''(t彼は 'SV = PVHV'はハッシュリファレンスであることを示しています) – ThisSuitIsBlackNot

+0

@ThisSuitIsBlackいいえ...ありがとう、ありがとう。 – zdim

+0

@ThisSuitIsBlackもう一度、ありがとうございました。これは驚きでした。すでに '$ ref'が悪いときにハッシュを使用することはありませんでした。 (私は本当にそれらの 'peek'ingツールを使用する方法を学ぶ必要があるので、私は推測する内部について) – zdim

5

%$hashは絶対にautovivifyありません。

$ perl -Mstrict -wE'my $foo; say $foo // "undef"' 
undef 

$ perl -Mstrict -wE'sub f { } my $bar; f(%$bar); say $bar // "undef"' 
HASH(0x10b50e0) 

エラーメッセージは、some_sub@_から、おそらく不適切な割り当てが起こっている何か他のものから来ています。

+1

"%$ hashは、関数(ユーザまたは組み込み関数)に渡されたときに絶対にオートバイバイジングする"一部の演算子では真である(例えば 'keys') – ThisSuitIsBlackNot

関連する問題