IT戦記

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

Perl で再帰呼出し時のスタック間データ共有

ダイナミックスコープがない言語では

再帰呼び出しのスタック間でデータを共有する場合は、以下のように仮引数を使わなければならない。*1

JavaScript木構造の探索をして、依存関係を直列に並べる例
function search(node, results, seen) {
  if(!results) results = [];
  if(!seen) seen = {};

  for(var i = 0; i < node.childs.length; i ++)
    search(node.childs[i], results, seen);

  if(!seen[node.name]){
    results.push(node); seen[node.name]=1;
  }

  return results;
}

var results = search(rootNode);

Perl では

ダイナミックスコープ(local)が使えるので、以下のように local でデータが共有できる。
ちなみに、ダイナミックスコープとは呼出元の変数を呼出先で参照できるようなスコープ。レキシカルスコープとは違う。

Perl木構造の探索して、依存関係を直列に並べる例
# package が Hoge の場合
sub search {
  my $node = shift;
  local $Hoge::results = $Hoge::results || [];
  local $Hoge::seen = $Hoge::seen || {};

  search($_) for(@{$node->childs});

  push(@{$Hoge::results}, $node) unless($Hoge::seen->{$node->name}++);

  return @{$Hoge::results};
}
my @results = search($root_node);

便利じゃない?

いや、便利かと思ったけど、よく見てみるとどっちもそんなに変わらないかもw まあ、local の使い方の勉強がてらに書いてみました。
いやー、Perlむずいわー。まだまだ、Perl ハッカーへの道は険しい。

*1:JSの場合は実はcalleeでもデータ共有できますがw