Ideally, the author of the function would have liked to use
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);
}
Unfortunately, that has a memory leak. The anon sub has a reference to $_fact
, which holds a reference to the anonymous sub. $_fact
would need to be cleared to break the reference on exit.
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 : ($@ || 'Unknown');
$_fact = undef;
die $e if $e
return $rv;
}
But that's UGLY! One way to avoid the problem is using a Y combinator. A much simpler way to avoid the problem is to store the code reference in a package variable instead of a lexical variable (since only lexical variables are captured by subs). This is what the code you posted does. Keep in mind that
*_fact = sub { ... };
is basically a run-time version of
sub _fact { ... }
Both assign the sub to CODE slot of symbol _fact
.
That said, 5.16 introduced a better fix:
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);
}