理想的には、機能の作者は、メモリリークが発生している残念ながら
sub fact {
my ($n) = @_;
my $_fact; $_fact = sub {
my ($n, $prod) = @_;
return $prod if $n == 0;
return $_fact->($n-1, $n*$prod);
};
return $_fact->($n, 1);
}
、使用することが好きだろう。 anon subには$_fact
への参照があり、匿名サブの参照が保持されています。終了時に参照を解除するには、$_fact
をクリアする必要があります。
sub fact {
my ($n) = @_;
my $_fact;
$_fact = sub {
my ($n, $prod) = @_;
return $prod if $n == 0;
return $_fact->($n-1, $n*$prod);
};
my $rv;
my $e = eval { $rv = $_fact->($n, 1); 1 } ? undef : ([email protected] || 'Unknown');
$_fact = undef;
die $e if $e
return $rv;
}
しかし、それは醜いです!問題を回避する方法の1つはY combinatorです。問題を回避するもっと簡単な方法は、レキシカル変数の代わりにパッケージ変数にコード参照を格納することです(字句変数のみがsubsによってキャプチャされるため)。これはあなたが投稿したコードが行うことです。
*_fact = sub { ... };
は、基本的
sub _fact { ... }
のランタイムバージョンの両方シンボル_fact
のCODEスロットにサブを割り当てることに留意してください。
、請求、5.16導入良く修正:
use feature qw(current_sub);
sub fact {
my ($n) = @_;
my $_fact = sub {
my ($n, $prod) = @_;
return $prod if $n == 0;
return __SUB__->($n-1, $n*$prod);
};
return $_fact->($n, 1);
}
"_factの前に*の正確な機能/目的は何ですか?" –
@ikegamiどうすればhttp://codepad.org/80KSqye4? –
それは漏れませんが、それは貧弱な解決策です。それは明らかにサブの設計における指導的要因であったテイル再帰を取り除く。 '$ n? $ n * fact($ n-1):1'はそうでなければ十分に成功しています。テール再帰を排除することで、どこでも非効率的になります。外側の部分を 'my $ rv = $ _fact(...);で終わるように変更する。 undef $ _fact; $ rv'がより適切でしょう。 – ikegami