問題描述
我在工作中學(xué)習(xí) Perl,并樂在其中.我通常用 Python 做我的工作,但老板想要 Perl.
I am learning Perl at my work and enjoying it. I usually do my work in Python but boss wants Perl.
Python 和 Perl 中的大多數(shù)概念都非常匹配:Python dictionary=Perl hash;Python 元組=Perl 列表;Python 列表=Perl 數(shù)組;等等.
Most of the concepts in Python and Perl match nicely: Python dictionary=Perl hash; Python tuple=Perl list; Python list=Perl array; etc.
問題:有沒有 Perl 版本的 Python 形式的 Iterator/生成器?
Question: Is there a Perl version of the Python form of an Iterator / Generator?
一個例子:生成斐波那契數(shù)的經(jīng)典 Python 方法是:
An example: A Classic Python way to generate the Fibonacci numbers is:
#!/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
如果您想根據(jù)需要生成更大列表的子部分,迭代器也很有用.Perl 的列表"看起來更靜態(tài)——更像是一個 Python 元組.在 Perl 中,foreach
可以是動態(tài)的還是僅基于靜態(tài)列表?
Iterators are also useful if you want to generate a subsection of a much larger list as needed. Perl 'lists' seem more static - more like a Python tuple. In Perl, can foreach
be dynamic or is only based on a static list?
Iterator 的 Python 形式是我已經(jīng)習(xí)慣的一種形式,但我沒有發(fā)現(xiàn)它在 Perl 中記錄...ex) 在 Perl 中編寫斐波那契子程序?是否有我缺少的 Perl yield
?
The Python form of Iterator is a form that I have gotten used to, and I do not find it documented in Perl... Other than writing this in loops or recursively or generating a huge static list, how do I (for ex) write the Fibonacci subroutine it in Perl? Is there a Perl yield
that I am missing?
具體來說——我該怎么寫:
Specifically -- how do I write this:
#!/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 . "
"; }
在此先感謝您對新手的善意...
Thanks in advance to being kind to the newbie...
推薦答案
為了比 Python 的生成器更靈活的解決方案,我編寫了模塊 List::Gen 在 CPAN 上提供隨機(jī)訪問惰性生成器數(shù)組:
For an even more flexible solution than Python's generators, I have written the module List::Gen on CPAN which provides random access lazy generator arrays:
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
由于生成器偽裝成數(shù)組,它們可以與普通的 perl 代碼無縫混合.還有一種面向?qū)ο蟮姆椒?
Since generators pretend to be arrays, they can mix seamlessly with normal perl code. There is also an object oriented approach:
my $fib; $fib = cache gen {$_ < 2 ? $_ : $fib->get($_ - 1) + $fib->get($_ - 2)};
say join ' ' => $fib->slice(0 .. 15);
在每種情況下,生成器都是惰性的,在創(chuàng)建時不計算任何內(nèi)容,然后只計算滿足切片所需的值.斐波那契數(shù)列的遞歸定義多次調(diào)用自身,所以使用 cache
函數(shù)來確保每個值只計算一次.
In each case, the generator is lazy, calculating nothing upon creation, and then calculating only those values required to satisfy the slices. The recursive definition of the Fibonacci sequence calls itself many times, so the cache
function is used to make sure each value is only calculated once.
您也可以將生成器用作迭代器:
You can also use generators as iterators:
while (my $num = $fib->next) {
last if $num > 10**15;
print "$_
";
}
$fib->next
也可以寫成$fib->()
.由于生成器還是隨機(jī)訪問的,所以可以$fib->reset()
或者$fib->index = 10;
$fib->next
can also be written $fib->()
. Since the generator is still random access, you can $fib->reset()
or $fib->index = 10;
如果您有任何問題,請告訴我.
Let me know if you have any questions.
更新:
我發(fā)布了該模塊的新版本 (0.80),它可以更輕松地在生成器中使用迭代算法.這是一個與 OP 的示例非常相似的示例:
I have released a new version of the module (0.80) that makes it easier to use iterative algorithms in generators. Here is an example that closely mirrors the OP's example:
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};
如果你在 sub 之前或頂部 使用 bigint;
,當(dāng)然可以:
if you use bigint;
before or at the top of the sub, you can of course:
say for @{fibonacci 400}; # or more
這篇關(guān)于Python 迭代器的 Perl 版本是什么?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!