我在我的工作中学习Perl并享受它。我通常做我的工作在Python,但老板想要Perl。
Python和Perl中的大多数概念很好地匹配:Python dictionary = Perl hash; Python tuple = Perl列表; python列表= Perl数组;等等
问题:是否有一个Perl版本的Iterator / Generator的Python形式?
#!/usr/bin/python def fibonacci(mag): a,b = 0,1 while a<=10**mag: yield a a,b = b,a+b for number in fibonacci(15): print "%17d" % number
如果您想根据需要生成大得多的列表的子部分,迭代器也很有用。 Perl’lists’似乎更加静态 – 更像是一个Python元组。在Perl中,foreach可以是动态的还是只基于静态列表?
Iterator的Python形式是一个我已经习惯了的形式,我没有发现它在Perl中记录…除了在循环或递归或生成一个巨大的静态列表,我如何(为ex)写在Perl的斐波那契子程序?有没有我缺少的Perl产量?
具体 – 我怎么写这个:
#!/usr/bin/perl use warnings; use strict; # yes -- i use those! sub fibonacci { # What goes here other than returning an array or list? } foreach my $number (fibonacci(15)) { print $number . "\n"; }
感谢提前对新人的亲切…
解决方法
为了比Python的生成器更灵活的解决方案,我已经在CPAN上编写了模块
List::Gen,它提供了随机访问延迟生成器数组:
use List::Gen; my $fib; $fib = cache gen {$_ < 2 ? $_ : $$fib[$_ - 1] + $$fib[$_ - 2]}; say "@$fib[0 .. 15]"; # 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610
因为生成器假装是数组,所以它们可以与正常的perl代码无缝地混合。还有一种面向对象的方法:
my $fib; $fib = cache gen {$_ < 2 ? $_ : $fib->get($_ - 1) + $fib->get($_ - 2)}; say join ' ' => $fib->slice(0 .. 15);
在每种情况下,生成器是惰性的,在创建时不计算任何值,然后仅计算满足切片所需的值。斐波那契序列的递归定义调用自身多次,因此缓存函数用于确保每个值只计算一次。
您还可以使用生成器作为迭代器:
while (my $num = $fib->next) { last if $num > 10**15; print "$_\n"; }
$ fib-> next也可以写成$ fib->()。因为生成器仍然是随机访问,你可以$ fib-> reset()或$ fib-> index = 10;
如果您有任何问题,请与我们联系。
更新:
我已经发布了一个新版本的模块(0.80),使得更容易在生成器中使用迭代算法。这里是一个例子,紧密地反映了OP的例子:
use List::Gen '*'; sub fibonacci { my $limit = 10**shift; my ($x,$y) = (0,1); While {$_ < $limit} gather { ($x,$y) = ($y,take($x) + $y) } } say for @{fibonacci 15};
如果你使用bigint;之前或在顶部的sub,你当然可以:
say for @{fibonacci 400}; # or more