Perl 5.20では、forループはモジュールスコープの変数を変更できますが、親スコープの字句変数は変更できないようです。forループは `my`変数を変更しませんが、` our`変数を変更します
#!/usr/bin/env perl
use strict;
use warnings;
our $x;
sub print_func {
print "$x\n";
}
for $x (1 .. 10) {
print_func;
}
印刷物あなたが期待するように1〜10は、しかし、次のようにはありません:
Use of uninitialized value $x in concatenation (.) or string at perl-scoping.pl line 8.
はここで何が起こっている:
#!/usr/bin/env perl
use strict;
use warnings;
my $x;
sub print_func {
print "$x\n";
}
for $x (1 .. 10) {
print_func;
}
は、次の警告を10回照射しますか? perlサブルーチンはネストすることはできません(常にモジュールスコープを持つことができます)。したがって、変数my
を閉じることができないことは論理的です。その場合には、strict
モードでperlは次のようなメッセージとともに、第2のプログラムを拒否すべきであるように思える:
Global symbol "$x" requires explicit package name at perl-scoping.pl line 6.
Global symbol "$x" requires explicit package name at perl-scoping.pl line 9.
すなわち、変数が宣言されていないため、フリー変数はどこでも宣言されていないため、サブルーチンを拒否する必要があります。
なぜPerlはこのように動作していますか?
'$ x(...){...}'のように聞こえるのは 'do {local $ x; $ x(...){...}}; 'に対して代入を行うと' 'Perl-scoping.plで字句変数$ xをローカライズできません...なぜそうではないのですか?元のバージョンでもエラーが発生しましたか? –
@GregoryNisbet 'local'はレキシカルでは動作しないので、' my $ x'がすでにスコープに入っていると思います。さもなければ、あなたの類推は、スコープ内に '$ x'がない場合、またはグローバル*の場合、基本的に正しい*です。スコープ内に '$ x'という字句がすでにある場合、' for $ x(...){...} 'の動作は変わります。この場合、 'for $ x'はループ内に新しい字句を宣言するので、' do {my $ x; $ x(...){...}}; 'のために。これは、なぜあなたは常に明示的に ''私の$ x'のために書くべきなのかの理由です。 – Schwern
私は現在、Perlの権限が厳密なモードで '$ x(...){...} 'を拒否したり、警告を出すことを決断しなかった理由を考えています。あなたはそれが前に出てきたかどうか知っていますか? –