_fact前面的*的确切功能/用途是什么?如何等效地编写它?

sub fact {
   my ($n) = @_;

   local *_fact = sub {
       my ($n, $prod) = @_;
       return $prod if $n == 0;
       return _fact($n-1, $n*$prod);
   };

   return _fact($n, 1);
}

fact($n);

最佳答案

理想情况下,该函数的作者希望使用

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子项具有对$_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 : ($@ || 'Unknown');
   $_fact = undef;
   die $e if $e
   return $rv;
}

但这太丑了!避免该问题的一种方法是使用Y combinator。避免此问题的更简单方法是将代码引用存储在包变量中,而不是词法变量中(因为subs仅捕获词法变量)。这就是您发布的代码的作用。请记住
*_fact = sub { ...  };

基本上是的运行时版本
sub _fact { ... }

两者都将sub分配给符号_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);
}

关于perl - 嵌套子前面的神秘*,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19777251/

10-15 09:08