加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

perl – 在嵌套sub前面的神秘*

发布时间:2020-12-15 23:34:46 所属栏目:大数据 来源:网络整理
导读:在_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); 解决方法 理想情况下,函数的
在_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 sub引用了$_fact,它保存了对匿名子的引用.需要清除$_fact以在退出时中断引用.

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

   my $_fact;
   $_fact = sub {
       my ($n,$n*$prod);
   };

   my $rv;
   my $e = eval { $rv = $_fact->($n,1); 1 } ? undef : ($@ || 'Unknown');
   $_fact = undef;
   die $e if $e
   return $rv;       
}

但那是个丑陋的!避免此问题的一种方法是使用Y combinator.避免问题的一种更简单的方法是将代码引用存储在包变量而不是词法变量中(因为只有子句捕获词法变量).这就是您发布的代码所做的事情.请记住

*_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,1);
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读