递归匿名函数来计算序列和

时间:2015-12-17 01:53:29

标签: perl recursion anonymous-function

我试着编写一个函数来计算以下内容, enter image description here

我能想到的就是这个,这是行不通的。

$fact = sub {
    $n = shift;
    if($n==0 || $n ==1){
        return 1;
    }else{
        return $n*&$fact($n-1);
    }
}

sub fun{
    ($x,$n)= @_;
    if($n==0){
        return 1;
    }elsif($n == 1){
        return $x;
    }else{
        return ($x)/&$fact($n)+fun($x,$n-1);
    }
}



print (fun(3,5));

1 个答案:

答案 0 :(得分:4)

首先,始终使用

use strict;
use warnings qw( all );

它会抓住你的一个错误。

其次,你错了你的sub,你错过了my,你发明了一个特例(自($x**1)/1! == $x [1] 。暂时不需要匿名,f就是:

sub f {
   my ($x, $n) = @_;
   return 1 if $n == 0;
   return ($x**$n) / fact($x) + f($x, $n-1);
}

同样,fact只是:

sub fact {
   my ($n) = @_;
   my $acc = 1;
   $acc *= $_ for 1..$n;
   return $acc;
}

关于这个问题,使递归函数匿名只是用__SUB__->(...) [2] 替换递归调用的问题,所以以下是匿名版本:

use feature qw( current_sub );

my $f = sub {
   my ($x, $n) = @_;
   return 1 if $n == 0;
   return ($x**$n) / fact($x) + __SUB__->($x, $n-1);
};

如果您希望fact也是匿名的,

use feature qw( current_sub );

my $f = sub {
   my ($x, $n) = @_;
   return 1 if $n == 0;

   my $fact = sub {
      my ($n) = @_;
      my $acc = 1;
      $acc *= $_ for 1..$n;
      return $acc;
   };

   return ($x**$n) / $fact->($x) + __SUB__->($x, $n-1);
};

也就是说,使用递归是这个函数的一个巨大的浪费。这是一个有效的实现:

my $f = sub {
   my ($x, $n) = @_;

   my $acc             = 1;
   my $numerator_acc   = 1;
   my $denominator_acc = 1;
   for (1..$n) {
      $numerator_acc   *= $x;
      $denominator_acc *= $_;
      $acc += ( $numerator_acc / $denominator_acc );
   }

   return $acc;
};
  1. 从技术上讲,你从($x**0)/0! == 1发明了两个,但$n == 0必须在某种程度上得到特别对待。

  2. Perl 5.16中引入了
  3. __SUB__。如果你想避免内存泄漏,那么之前会更复杂。