什么是Python迭代器的Perl版本?

什么是Python迭代器的Perl版本?,python,perl,iterator,Python,Perl,Iterator,我在工作中学习Perl,并享受它。我通常用Python做我的工作,但老板想要Perl Python和Perl中的大多数概念非常匹配:Python字典=Perl哈希;Python tuple=Perl列表;pythonlist=Perl数组;等等 问题:是否有一个Perl版本的Python形式的/Generator 例如:生成斐波那契数的经典Python方法是: #!/usr/bin/python def fibonacci(mag): a, b = 0, 1 while a

我在工作中学习Perl,并享受它。我通常用Python做我的工作,但老板想要Perl

Python和Perl中的大多数概念非常匹配:Python字典=Perl哈希;Python tuple=Perl列表;pythonlist=Perl数组;等等

问题:是否有一个Perl版本的Python形式的/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

提前感谢您对新手的友好…

这里有一个很好的实用示例和一篇PDF文章。。。但是我对Perl太生疏了,无法尝试直接实现您的挑战(正如您将看到的,PDF中的示例和方法都使用了不太直接的方法)。

有一个很好的实用示例和一篇PDF文章。。。但是我对Perl太生疏了,无法尝试直接实现您的挑战(正如您将看到的,PDF中的示例和方法都使用了一种不太直接的方法)。

有一种类似的方法来生成迭代器/生成器,但它不是Python上的“一流公民”

在Perl中,如果您看不到您想要的内容(经过一次强制第一次!),您可以使用类似于基于Perl闭包和匿名子例程的Python迭代器的方法

考虑:

use strict; use warnings;

sub fibo {
    my ($an, $bn)=(1,0);
    my $mag=(shift || 1);
    my $limit=10**$mag;
    my $i=0;

    return sub {
        ($an, $bn)=($bn, $an+$bn);      
        return undef if ($an >=$limit || wantarray );
        return $an;
    }
}

my $num;
my $iter=fibo(15);
while (defined($num=$iter->()) ) { printf "%17d\n", $num; }
sub
fibo
维护一个Perl,允许维护持久变量。你可以通过拥有一个类似C/C++的模块来完成同样的操作。在
fibo
内部,一个匿名子例程执行返回下一个数据项的工作

引用“在你了解标量和列表上下文之间的区别之前,你会很痛苦”——第69页(一本极力推荐的书,顺便说一句…)

在这种情况下,annon子对象仅返回一个值。我在Perl中知道的唯一可以在标量上下文中工作的循环机制是
;我想其他人在继续之前会先填好名单。因此,如果在列表上下文中调用anon-sub,它将尽职尽责地返回下一个fibonacci数,这与Python对迭代器的调用不同,循环将终止。这就是为什么我将
返回undef if。。。。wantarray
,因为它在编写的列表上下文中不起作用

有办法解决这个问题。实际上,您可以编写类似于
map
foreach
等的子例程,但它并不像Python那样简单。您需要在foreach循环中使用一个附加函数。折衷是Perl方法具有巨大的功能和灵活性


您可以在Mark Jason Dominus的优秀著作《高阶Perl》中阅读有关Perl迭代器的更多信息。brian d foy在Perl评论中也有一篇关于Interators的优秀文章。

有一种类似的方法来生成迭代器/生成器,但它不是Python上的“一流公民”

在Perl中,如果您看不到您想要的内容(经过一次强制第一次!),您可以使用类似于基于Perl闭包和匿名子例程的Python迭代器的方法

考虑:

use strict; use warnings;

sub fibo {
    my ($an, $bn)=(1,0);
    my $mag=(shift || 1);
    my $limit=10**$mag;
    my $i=0;

    return sub {
        ($an, $bn)=($bn, $an+$bn);      
        return undef if ($an >=$limit || wantarray );
        return $an;
    }
}

my $num;
my $iter=fibo(15);
while (defined($num=$iter->()) ) { printf "%17d\n", $num; }
sub
fibo
维护一个Perl,允许维护持久变量。你可以通过拥有一个类似C/C++的模块来完成同样的操作。在
fibo
内部,一个匿名子例程执行返回下一个数据项的工作

引用“在你了解标量和列表上下文之间的区别之前,你会很痛苦”——第69页(一本极力推荐的书,顺便说一句…)

在这种情况下,annon子对象仅返回一个值。我在Perl中知道的唯一可以在标量上下文中工作的循环机制是
;我想其他人在继续之前会先填好名单。因此,如果在列表上下文中调用anon-sub,它将尽职尽责地返回下一个fibonacci数,这与Python对迭代器的调用不同,循环将终止。这就是为什么我将
返回undef if。。。。wantarray
,因为它在编写的列表上下文中不起作用

有办法解决这个问题。实际上,您可以编写类似于
map
foreach
等的子例程,但它并不像Python那样简单。您需要在foreach循环中使用一个附加函数。折衷是Perl方法具有巨大的功能和灵活性


您可以在Mark Jason Dominus的优秀著作《高阶Perl》中阅读有关Perl迭代器的更多信息。brian d foy在Perl评论中也有一篇关于Interators的优秀文章。

迭代器的概念在Perl中有点不同。基本上,您希望在持久变量上返回一个一次性子例程“closed”

use bigint;
use strict;
use warnings;

sub fibonacci {
    my $limit = 10**( shift || 0 );
    my ( $a, $b ) = ( 0, 1 );
    return sub { 
        return if $a > $limit;
        ( my $r, $a, $b ) = ( $a, $b, $a + $b );
        return $r;
    };
}
my $fit = fibonacci( 15 );
my $n = 0;
while ( defined( my $f = $fit->())) { 
     print "F($n): $f\n";
     $n++;
}
如果你不喜欢
while
循环,那么这里有两个语法糖,基本上完成了一个each item循环:

sub iterate ($$) {
    my $iter   = shift;
    my $action = shift;
    while ( defined( my $nextval = $iter->())) { 
        local *_ = \$nextval;
        $action->( $_ );
    }
    return;
}

iterate fibonacci( 15 ) => sub { print "$_\n"; };

sub iter (&$) { 
    my $action = shift;
    my $iter   = shift;
    while ( defined( my $nextval = $iter->())) { 
        local *_ = \$nextval;
        $action->( $_ );
    }
    return;
}

iter { print "$_\n" } fibonacci( 15 );

迭代器的概念在Perl中有点不同。基本上,您希望在持久变量上返回一个一次性子例程“closed”

use bigint;
use strict;
use warnings;

sub fibonacci {
    my $limit = 10**( shift || 0 );
    my ( $a, $b ) = ( 0, 1 );
    return sub { 
        return if $a > $limit;
        ( my $r, $a, $b ) = ( $a, $b, $a + $b );
        return $r;
    };
}
my $fit = fibonacci( 15 );
my $n = 0;
while ( defined( my $f = $fit->())) { 
     print "F($n): $f\n";
     $n++;
}
如果你不喜欢
while
循环,那么这里有两个语法糖,基本上完成了一个each item循环:

sub iterate ($$) {
    my $iter   = shift;
    my $action = shift;
    while ( defined( my $nextval = $iter->())) { 
        local *_ = \$nextval;
        $action->( $_ );
    }
    return;
}

iterate fibonacci( 15 ) => sub { print "$_\n"; };

sub iter (&$) { 
    my $action = shift;
    my $iter   = shift;
    while ( defined( my $nextval = $iter->())) { 
        local *_ = \$nextval;
        $action->( $_ );
    }
    return;
}

iter { print "$_\n" } fibonacci( 15 );
这本优秀的书(在指定的链接上免费提供)包含了大量相关主题的信息,特别是有一整章关于迭代器的内容。通过“更高阶”,作者暗示了使用Perl的功能作为一种具有一流函数的函数式语言来实现各种很酷的东西。这真的是一本非常好的书——我读了大部分,关于迭代器和流的章节非常棒。如果您打算编写Perl代码,我强烈建议您至少浏览一下它。

这本优秀的书(在指定的链接上免费提供)包含了大量有关相关主题的信息,特别是有一整章关于迭代器。通过“更高阶”,作者暗示了使用Perl的功能作为一种具有一流函数的函数式语言来实现各种很酷的东西。这真是一个好消息
while (my $num = $fib->next) {
    last if $num > 10**15;
    print "$_\n";
}
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};
say for @{fibonacci 400}; # or more
use strict;
use warnings;

use Memoize;
memoize('fib');

foreach my $i (1..15) {
  print "$i -> ",fib($i),"\n";
}

sub fib {
  my $n = shift;
  return $n if $n < 2;
  fib($n-1) + fib($n-2);
}
#!/usr/bin/perl -w

use strict; use warnings; 
use Alef;

my $fibo;

BEGIN {

    my ($a, $b) = (0, 1);

    $fibo = sub {
        ($a, $b) = ($b, $a+$b);
        $a;
    }
}

my $fibonacci = new Alef($fibo);

foreach my $number ($fibonacci->take(15)){ print $number . "\n"; }
sub take {

    my ($self,$n) = (@_);

    my @these = ();

    my $generator = $self->{'generator'};
    for (1..$n){
        push(@these,$self->{'this'});
        $self->{'this'} = &$generator($self->{'this'});
    }
    @these;
}
use 5.016;
use warnings;
use Coro::Generator;

sub gen_fibonacci {
    my $mag = shift;
    generator {
        my ($a, $b) = (0, 1);
        while ($a <= 10 ** $mag) {
            yield $a;
            ($a, $b) = ($b, $a + $b);
        }   
        yield undef;  # stop it!
    };  
}   

my $fibonacci = gen_fibonacci(15);

while (defined (my $number = $fibonacci->())) {
    printf "%17d\n", $number;
}