Perlで初期化されていないハッシュキーのデフォルト値はゼロですか?
-
03-07-2019 - |
質問
次のようなPerlコードがあります:
# -- start --
my $res;
# run query to fetch IPv6 resources
while( my $row = $org_ip6_res->fetchrow_arrayref )
{
if( $row->[4] =~ /PA/ ) {
$res->{ipv6}{pa}{$row->[2]}++;
} elsif( $row->[4] eq 'PI' ) {
$res->{ipv6}{pi}{$row->[2]}++;
}
}
# -- stop --
クエリ結果を反復する前に $ res
が設定されることはありませんが、コードは正常に実行されます。
各値の前にprintステートメントを置くと、どちらの場合も空白になりますが、増分が適用された後にprintステートメントが来ると、組織にあるIPv6リソースの数に応じて> = 1の値を取得します。
私の質問は、Perlの初期化されていないハッシュキーの値が自動的に0になることを意味すると思いますか?
初心者の質問に出くわして申し訳ありませんが、私はそのような構成体に精通していないだけです
つまり、 $ hashref-> {foo}-> {bar} ++
ここで、値はまだ $ hashref-> {foo}-> {bar}
に明示的に割り当てられていません。事前に感謝します!
解決
値は自動的にゼロになりません。値は最初は未定義です。ただし、数値のように処理する場合(たとえば、 ++
を適用する場合)、Perlはゼロのように処理します。文字列のように処理する場合(たとえば、。
を適用する場合)、Perlは空の文字列のように処理します。
perldoc perlsyn
の「宣言」の下:
宣言する必要がある唯一のもの Perlはレポート形式であり、 サブルーチン(そして時には サブルーチン)。変数は 未定義の値(" undef")があるまで 定義された値が割り当てられ、 は「undef」以外です。いつ 数字として使用される" undef"扱われます 0として;文字列として使用する場合、 空の文字列として扱われる"&quot ;;そして 参照として使用されていない場合 に割り当てられているものとして扱われます エラー。
他のヒント
Telemachusの投稿について詳しく説明するために、初期化されていない値は定義されていません。構造の深い部分は autovivified です。これは、データ構造が自動的に作成される便利な機能です。自己活性化は、必要なときに優れていますが、予防したい場合は苦痛になります。ネットの周りには、autovivificationの理解に関する多くのチュートリアル、記事、および投稿があります。
したがって、未定義の $ ref
および $ ref-> {ipv6} {pa} {'foo'} ++
、 $ ref
には次の値が割り当てられます:
$ref = {
ipv6 => {
pa => {
foo => undef
}
}
};
その後、undefがインクリメントされます。undefが0に数値化されるため、1である0 ++が得られます。
最終結果: ref-> {ipv6} {pa} {'foo'} == 1
。
警告を有効にしている場合( use warnings;
を使用しますか?)、「初期化されていない値」を取得します。これらの未定義の値を操作すると警告が表示されます。ユニット化された値をインクリメントすることが望ましい動作である場合、コードの限られた部分で警告の望ましいグループをオフにすることができます:
use strict;
use warnings;
my $res;
// run query to fetch IPv6 resources
while( my $row = $org_ip6_res->fetchrow_arrayref )
{ no warnings 'uninitialized';
if( $row->[4] =~ /PA/ ) {
$res->{ipv6}{pa}{$row->[2]}++;
} elsif( $row->[4] eq 'PI' ) {
$res->{ipv6}{pi}{$row->[2]}++;
}
}
perllexwarn に警告階層があります。
基本的には未定義ですが、インクリメントするとゼロであるかのように扱われます。
Perlの用語では、用語は「autovivified」です。
おそらくやりたいのは、 existsキーワードを使用することです。
>$res->{ipv6}{pa}{$row->[2]}++ if exists($res->{ipv6}{pa}{$row->[2]});
初期化されていないハッシュ key などはありません。初期化されない可能性があるのは、特定のキーの値です。ハッシュ値は単なるスカラー値です。 $ foo
のような変数と違いはありません。
この例では、相互作用するPerlの機能がいくつかあります。
最初は $ res
は未定義です(つまり、値は undef
です)。初期化されていない値をハッシュリファレンスとして使用する場合( $ res-> {ipv6} ...
など)Perl" autovivifies"それを一つとして。つまり、Perlは匿名ハッシュを作成し、 undef
の値を新しいハッシュへの参照に置き換えます。このプロセスは、結果の値を参照として使用するたびに(サイレントに)繰り返されます。
最終的に、未定義の $ res-> {ipv6} {pa} {$ row-> [2]}
への道を自動化します。これは $ foo
のような単なるスカラー値であることを忘れないでください。動作は次のことと同じです
my $foo;
$foo++;
未定義の値を使用すると、Perlは特別な処理を行います。それらを数字として使用する場合、Perlはそれらを0に変換します。文字列として使用する場合、Perlはそれらを ''(空の文字列)に変換します。ほとんどの場合、「初期化されていない値を使用...」というメッセージが表示されます。警告を有効にしている場合は警告(必要です)。 auto-increment 演算子( + +
)は特殊なケースです。便宜上、値をインクリメントする前に undef
から 0
に静かに変換します。