{
sub a {
print 1;
}
}
a;
バグですか?
a
外部からは利用できません。
Perl 6* で動作しますか?
※申し訳ありませんが、まだインストールしていません。
サブがブロックの外に見える理由を尋ねていますか? もしそうなら、それはコンパイル時のsub
キーワードがサブを名前空間に置くためです(キーワードを使用して新しい名前空間を作成しmain
ない限り)。package
次のようなものを試すことができます
{
my $a = sub {
print 1;
};
$a->(); # works
}
$a->(); # fails
この場合、sub
キーワードはサブルーチンを作成してmain
名前空間に配置するのではなく、匿名サブルーチンを作成してレキシカル スコープの変数に格納します。変数がスコープ外になると、(通常は) 使用できなくなります。
詳細を読むには、チェックアウトしてくださいperldoc perlsub
また、Perl パーサーがコードを認識する方法を検査できることもご存知でしたか? のようにフラグ-MO=Deparse
を付けて perl を実行しperl -MO=Deparse yourscript.pl
ます。元のコードは次のように解析されます。
sub a {
print 1;
}
{;};
a ;
サブルーチンが最初にコンパイルされ、次にブロックがコードなしで実行され、次にa
呼び出されます。
Perl 6 での私の例については、「成功」、「失敗」を参照してください。Perl 6 では、逆参照は では.
ないことに注意してください->
。
編集: Perl 5.18 で期待されるレキシカル サブルーチンの新しい実験的サポートに関する別の回答を追加しました。
Perl 6では、潜水艦は確かに字句スコープであるため、コードはエラーをスローします(すでに数人が指摘しているように)。
これにはいくつかの興味深い意味があります。
サブルーチンは、ブロック スコープではなく、パッケージ スコープです。
#!/usr/bin/perl
use strict;
use warnings;
package A;
sub a {
print 1, "\n";
}
a();
1;
package B;
sub a {
print 2, "\n";
}
a();
1;
Perlの名前付きサブルーチンは、グローバル名として作成されます。他の回答は、匿名のサブルーチンを字句変数に割り当てることによって字句サブルーチンを作成する方法を示しています。もう1つのオプションは、local
変数を使用して動的スコープのサブを作成することです。
2つの主な違いは、呼び出しスタイルと可視性です。動的スコープのサブは、名前付きサブのように呼び出すことができ、定義されているブロックがなくなるまでグローバルに表示されます。
use strict;
use warnings;
sub test_sub {
print "in test_sub\n";
temp_sub();
}
{
local *temp_sub = sub {
print "in temp_sub\n";
};
temp_sub();
test_sub();
}
test_sub();
これは印刷する必要があります
in temp_sub
in test_sub
in temp_sub
in test_sub
Undefined subroutine &main::temp_sub called at ...
@tchristによる別の叱責の危険を冒して、私は完全性のために別の答えを追加しています。まだリリースされていないPerl5.18には、実験的な機能として字句サブルーチンが含まれていると予想されます。
関連するドキュメントへのリンクは次のとおりです。繰り返しになりますが、これは非常に実験的なものであり、次の2つの理由から本番コードには使用しないでください。
だから、あなたが望むなら、この新しいおもちゃで遊んでください、しかしあなたは警告されました!
コードがコンパイルされ、実行され、「1」が表示される場合、バグは発生していません。
サブルーチンは、それらが定義されている字句スコープ内でのみ呼び出し可能であると期待しているようです。それは、他のファイルで定義されたサブルーチンを呼び出すことができないことを意味するため、悪いことです。おそらく、各ファイルが独自のレキシカル スコープで評価されることに気付いていないでしょうか? それは好きなものを可能にします
my $x = ...;
sub f { $x }
はい、これは設計上の欠陥だと思います。具体的には、Perl で作成された字句スコープではなく動的スコープを使用するという最初の選択が、自然にこの動作につながります。しかし、すべての言語設計者とユーザーが同意するわけではありません。したがって、あなたが尋ねる質問には明確な答えがありません。
レキシカル スコープは Perl 5 で追加されましたが、オプション機能として、常に具体的に示す必要があります。その設計上の選択には完全に同意します。下位互換性は重要です。