警告を有効にすると、perl は通常、 が式で使用され、値が割り当てられていないUse of uninitialized value $foo
場合$foo
に出力しますが、場合によっては問題なく、変数はfalse、0
、または''
警告なしで処理されます。
初期化されていない/未定義の変数を警告なしで使用できるのはどのような場合ですか?
perlsyn のドキュメントによると、
数値
0
、文字列'0'
および''
、空のリスト()
、およびundef
は、ブール値のコンテキストではすべて false です。他のすべての値は true です。
未定義値がfalseなので、以下のプログラム
#! /usr/bin/perl
use warnings;
my $var;
print "A\n" if $var;
$var && print "B\n";
$var and print "C\n";
print "D\n" if !$var;
print "E\n" if not $var;
$var or print "F\n";
$var || print "G\n";
警告なしで出力D
します。G
コードでスカラーを少なくとも 1 回インクリメントまたはデクリメントする場合は、スカラーを明示的にゼロに初期化する必要はありません。
#! /usr/bin/perl
use warnings;
my $i;
++$i while "aaba" =~ /a/g;
print $i, "\n";
上記のコード3
は、警告なしで出力します。
暗黙的なゼロと同様に、少なくとも 1 回追加する場合は、スカラーを空の文字列に明示的に初期化する必要はありません。
#! /usr/bin/perl
use warnings;
use strict;
my $str;
for (<*>) {
$str .= substr $_, 0, 1;
}
print $str, "\n";
その一例が「自動生存」です。ウィキペディアの記事から:
Autovivification は、データ構造の動的な作成を伴う Perl プログラミング言語の特徴的な機能です。Autovivification は、未定義の値が逆参照されたときに変数参照を自動的に作成することです。つまり、Perl の自動有効化により、プログラマーは、変数の存在とその完全な構造を事前に明示的に宣言することなく、構造化変数とその構造化変数の任意のサブ要素を参照できます。
例えば:
#! /usr/bin/perl
use warnings;
my %foo;
++$foo{bar}{baz}{quux};
use Data::Dumper;
$Data::Dumper::Indent = 1;
print Dumper \%foo;
中間キーを明示的に初期化しなくても、Perl が足場を処理します:
$VAR1 = { 'バー' => { 'バズ' => { 'quux' => '1' } } };
自動有効化がなければ、コードにはより多くのボイラープレートが必要になります。
my %foo;
$foo{bar} = {};
$foo{bar}{baz} = {};
++$foo{bar}{baz}{quux}; # finally!
自動有効化を、それが生成する可能性のある未定義の値と混同しないでください。たとえば、
#! /usr/bin/perl
use warnings;
my %foo;
print $foo{bar}{baz}{quux}, "\n";
use Data::Dumper;
$Data::Dumper::Indent = 1;
print Dumper \%foo;
我々が得る
./prog.pl 行 6 の出力で初期化されていない値が使用されています。 $VAR1 = { 'バー' => { 'baz' => {} } };
中間キーが自動有効化されたことに注意してください。
自動有効化のその他の例:
配列への参照
my $a;
push @$a => "foo";
スカラーへの参照
my $s;
++$$s;
ハッシュへの参照
my $h;
$h->{foo} = "bar";
悲しいことに、Perl は (まだ!) 以下を autovivify しません:
my $code;
$code->("Do what I need please!");
同様の質問への回答で、ysth は報告しています。
特定の演算子は、左側または唯一のオペランドのデフォルト値 0 または "" が意味をなす状況で一般的に使用されるため、利便性のために「初期化されていない」警告を意図的に省略しています。
これらは次のとおりです。および(
++
前または--
後) 、、、、、、、+=
-=
.=
|=
^=
&&=
||=
「定義されたまたは」で//=
あることは、警告なしで未定義の値を喜んで変更します。
これまでのところ、私が見つけたケースは次のとおりです。
if $foo
またはのようなブールコンテキスト$foo || $bar
++
またはで--
+=
、、、-=
またはの左側.=
他にありますか?
厄介な迷惑な警告であっても、常に警告を修正してください。
未定義の警告はオフにすることができます。これを行うには、操作の新しいスコープを作成します。詳細については、を参照perldoc perllexwarn
してください。この方法は、perl のすべてのバージョンで機能します。
{
no warnings 'uninitialized';
my $foo = "foo" + undef = "bar";
}
多くの二項演算子については、新しい Perl 5.10 のものを使用でき~~
ます//
。詳細については、を参照perldoc perlop
してください。
use warnings;
my $foo = undef;
my $bar = $foo // ''; ## same as $bar = defined $foo ? $foo : ''
//=
未定義の場合に変数を設定するバリアントもあります。
$foo //= '';
スマート マッチング ( ~~
) 演算子はちょっとクールで、スマートな比較を可能にしperldoc perlsyn
ます。
use warnings;
my $foo = "string";
say $foo eq undef; # triggers warnings
say $foo ~~ undef; # no undef warnings
本当の答えは次のとおりです。なぜその警告をオンにしたいのですか? undef は、変数としては完全に適切な値です (データベースを扱ったことのある人なら誰でもわかるように)。多くの場合、true (何かが起こった)、false (何も起こらなかった)、および undef (エラーが発生した) を区別することが理にかなっています。
と言うより、
use strict;
use warnings;
いう
use common::sense;
警告のすべての利点が得られますが、未定義の変数のような厄介なものはオフになっています。
common::sense は CPAN から入手できます。