IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

Perl で JS の arguments.callee 的なことしようと思ってハマった

JavaScript では

arguments.callee を使うと以下のように無名関数の再帰が書ける

(function(c) {
  if (c == undeinfed) c = 10;
  console.log(c);
  if (c--) arguments.callee(c);
});

Perl

そういうことをやる方法を知らないので

do {
  my $c = 10;
  my $callee = sub {
    print "$c\n";
    &$callee if ($c--);
  };
}->();

とやろうと思ったら怒られた><

なんで怒られたれたかというと

sub は作られた時点のレキシカル変数しか記憶しないからのようだ。
さっきの例の

my $callee = sub { ... };

では、 sub { ... } の評価が my より先に行われる。
なので、 sub { ... } が出来た時点で $callee という変数は存在しない。
なので、 sub { ... } の中から変数 $callee を参照することができない。
ということらしい。
以下のようにすれば

my $callee; $callee = sub { ... };

$callee は問題なく呼び出せた

でも

なんで、わざわざ出来た時点の状態を保持しているんだろう。
単純にスコープの参照を持っていればいいだけで、その時の変数の状態まで sub { ... } 保存する必要ないと思うなあ。

(追記)

やり方を教えてもらいました><
Devel::Caller が便利すぎる件について - IT戦記