drkcore

2007/09/01 23:33:42

perlでcall-with-procedure

参考にしたサイト

継続渡しスタイルに載ってたcall-with-procedureをperlで。

sub call_with_procedure {
  my ($exp,$proc) = @_;
  $proc->($exp);
}

sub fact {
  my $n = shift;
  $n == 1 ? 1 : $n * fact($n-1);
}

print call_with_procedure(sub {2 * $_[0]}, sub {$_[0]->(fact(10))});

実行すると

$ perl curpr.pl 
7257600

継続ってのはgaucheだと外に向いているようなものを内側にひっくり返す感があってなんか奇妙な感じがするが、いくつか書いてみてから継続の説明を読むと、なんかフムフム感が得られる。だけど、それをperlでやろうとするとひどく混乱するのはなぜだろうか?

sub {$_[0]->(fact(10))}->(sub {2 * $_[0]})
= {2 * $_[0]}->(fact(10))
= 2 * fact(10)

書き下してみるとこんな感じか、、、、

最初のsub{}->()ってコードはautoboxを使えば動きそうな気がするが、、、

実際にやってみることにした。

use autobox;
use autobox::Core;

sub fact {
  my $n = shift;
  $n == 1 ? 1 : $n * fact($n-1);
}

print sub {$_[0]->(fact(10))}->(sub {2 * $_[0]});

無名サブルーチンが第一引数に無名サブルーチンを取ってこれが引数にfact10の結果を取ってそれを二倍するっていう処理が実行される(はず)

$ perl abtest.pl 
7257600

動いた!

call/ccの勉強してたのに、キモコードを動かすというあらぬ方向に行ってしまったが、ファーストクラスオブジェクトってのがなんだかわかったようなわからんようなホンワカした何かを得た感があったのでよしとしよう。

Comments