16

警告を有効にすると、perl は通常、 が式で使用され、値が割り当てられていないUse of uninitialized value $foo場合$fooに出力しますが、場合によっては問題なく、変数はfalse0、または''警告なしで処理されます。

初期化されていない/未定義の変数を警告なしで使用できるのはどのような場合ですか?

4

4 に答える 4

19

概要

  • ブール値テスト
  • 未定義値の増減
  • 未定義の値への追加
  • 自動生存
  • その他のミューテーター

ブール値テスト

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 は、データ構造の動的な作成を伴う Pe​​rl プログラミング言語の特徴的な機能です。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 または "" が意味をなす状況で一般的に使用されるため、利便性のために「初期化されていない」警告を意図的に省略しています。

これらは次のとおりです。および(++前または--後) 、、、、、、、+=-=.=|=^=&&=||=

「定義されたまたは」で//=あることは、警告なしで未定義の値を喜んで変更します。

于 2010-01-30T02:32:51.893 に答える
2

これまでのところ、私が見つけたケースは次のとおりです。

  • 自動生存(gbaconの答え
  • if $fooまたはのようなブールコンテキスト$foo || $bar
  • ++またはで--
  • +=、、、-=またはの左側.=

他にありますか?

于 2010-01-30T02:54:10.403 に答える
2

厄介な迷惑な警告であっても、常に警告を修正してください。

未定義の警告はオフにすることができます。これを行うには、操作の新しいスコープを作成します。詳細については、を参照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
于 2010-01-31T17:14:34.697 に答える
0

本当の答えは次のとおりです。なぜその警告をオンにしたいのですか? undef は、変数としては完全に適切な値です (データベースを扱ったことのある人なら誰でもわかるように)。多くの場合、true (何かが起こった)、false (何も起こらなかった)、および undef (エラーが発生した) を区別することが理にかなっています。

と言うより、

use strict;
use warnings;

いう

use common::sense;

警告のすべての利点が得られますが、未定義の変数のような厄介なものはオフになっています。

common::sense は CPAN から入手できます。

于 2010-01-31T16:43:43.537 に答える