小池啓仁 ヒロヒト応援ブログ By はてな

小池啓仁(コイケヒロヒト)の動画など。

小池啓仁 ヒロヒト応援ブログ By はてな

無名サブルーチンとクロージャ

昨日言っていた『インナーサブルーチンを使って親のレキシカル変数をリターン値にすると、初回の値を保持するようなのです』の性質を利用するとstatic変数だけでなく、クロージャも出来ますね!

◆サンプル(closure.pl)

use strict;
use warnings;

sub closure {
    my $value = shift;
    sub { $value++ };
}

my $c = closure(100);
print $c->(), "\n";
print $c->(), "\n";
print $c->(), "\n";
print $c->(), "\n";

◆実行結果

C:\samp_pl>closure.pl
100
101
102
103

closureサブルーチンを初回コールすることにより、$valueに初期値をセットし、$valueをカウントする無名サブルーチンリファレンスを返します。この時点で$valueはstatic変数になっていますね。


そのリファレンスをスカラー変数($c)へ代入し、無名サブルーチンを実行するとstatic変数$valueがカウントされ100〜103のように出力されるわけです。


と、大まかに説明しましたが、無名サブルーチン『sub { $value++ };』のところをもうちょっと詳しく説明します。
名前の無いサブルーチンを無名サブルーチンといいます(まんま)。


無名サブルーチンは、名前が無いのでスカラー変数に代入したり、return値に指定したりします。
今回はreturn値に指定しています。ただし、returnキーワードは省略されています。
その指定された値は、サブルーチンのリファレンスになっています。


無名サブルーチンを実行するには、代入したスカラー変数からデリファレンスの『->』とサブルーチンの『()』を繋げて『$c->()』という感じで実行します。


また、Perlのサブルーチンでは最後に評価された式がreturn値になりますので、上記のclosureは以下と等価なのです。

sub closure {
    my $value = shift;
    return  sub { 
               return $value++; 
            };
}

初心者の内は、この辺でつまずくんだよなぁ・・・。
それから、クロージャそのものについては、私も詳しくないのでネットで検索してください。