2011-01-27 6 views
4

perlのクロージャと$1の正規表現の変数にバグが見つかりました。単純に、それらは一緒に混合しません。perlのクロージャと正規表現の変数

このコードを考えてみましょう。

use warnings; 

while ("1234567890"=~/(.)/sg) { 
    push @subs, sub{print $1;}; 
} 

for (@subs) {$_->()} 

あなたはperlは今、すべての数字を印刷することを想像 - その代わり、私は未定義$1から10回の警告を得ました。

本当にバグですか、それともperlのドキュメントで何かを見逃してしまったのですか?なんらかの理由がありますが、なぜ$1は定義されておらず、クロージャの一部ではありませんか?

答えて

7

私は答えがperl closures and $_の答えに似ていると思います。 $1もグローバル変数です。あなたがする必要がどのような

は次のとおりです。

my $x = $1; 
push @subs, sub{print $x;}; 
+0

ああ、ええ、それは理にかなって:)しかし、私はあなたが印刷$ xをメンターと思います。 –

+0

ありがとう、それを修正しました(: –

8

Perlのは、2つの独立したが、主に互換性のある変数のシステムを持っています。シンボルテーブルにあるグローバル変数と、レキシカルパッドにバインドされた範囲にあるレキシカル変数。

グローバル変数は、シンボリック逆参照の対象となり、localでダイナミックスコープに従います。字句変数(myで定義)は閉じられます。

正規表現のマッチ変数(およびPerlの他のすべての特殊変数)はシンボルテーブル内のグローバル変数であるため、それらをクローズする方法はありません。

はただ字句に値をコピーし、これを修正するには、次の

use warnings; 

while ("1234567890"=~/(.)/sg) { 
    my $x = $1;    # creates a new lexical that the sub closes over 
    push @subs, sub{print $x;}; 
} 

for (@subs) {$_->()} 
+0

答えがありがとう、ありがとう、彼は速くてポイントが少ないので、ナイロンに最善の答えを加えました:)私は2つの最高の答えを選ぶことができません –

+1

マッチ変数は、再帰的な関数を除き、自動的にローカライズされたグローバルのようなものです。 –