[Perl]猿でもわかるクロージャ超入門
上記のJavaScript版の記事を読んだという前提で解説させていただきます。
問題
呼び出すたびに、1,2,3,...を返すような関数f( )を定義せよ。f(); // 1
f(); // 2
f(); // 3
クロージャ その1
JS版のクロージャに似せて書くとこうなります。#!/usr/bin/perl
use strict;
use warnings;
sub outer {
my $i = 1;
return sub {
print "$i\n";
$i++;
};
}
my $f = outer();
$f->(); # 1
$f->(); # 2
$f->(); # 3
JS版とそっくりですね~。
関数のリファレンスを使っているので、呼び出し方法が$f->()のような形になっちゃいますが、そこはご愛嬌ということで。
クロージャ その2
JSと違ってPerlでは中カッコ{}でスコープを作ることができるので、より簡潔に書けます。#!/usr/bin/perl
use strict;
use warnings;
my $f;
{
my $i = 1;
$f = sub {
print "$i\n";
$i++;
};
}
$f->(); # 1
$f->(); # 2
$f->(); # 3
クロージャ その3
Perlではローカルスコープ内で宣言した関数を、スコープ外から参照することができます。これを利用すると、さらに短く書けます。
#!/usr/bin/perl
use strict;
use warnings;
{
my $i = 1;
sub f {
print "$i\n";
$i++;
}
}
f();
f();
f();
以上、Perlでのクロージャの作り方でした。他にもいろいろ書き方があると思います。
Perlってサイコー!!
クロージャの使われどころ
PerlにはClass::AccessorやClass::Data::Inheritablenaといった、オブジェクト指向をより便利にするための定番モジュールがあります。これらのモジュールでは、クロージャを使うことによってアクセサを実現しています。
参考
-
はてな匿名ダイアリー:PerlのClass::Data::Inheritableの解析
軽妙な語り口でClass::Data::Inheritableの実装を解説してくれる。もはやこれは文学だ。
Perl のクロージャ - naoyaのはてなダイアリー
クロージャの応用方法について深堀したい方はこちら。