Perl 如何使用List::Gen编写Collatz序列?

Perl 如何使用List::Gen编写Collatz序列?,perl,collatz,Perl,Collatz,我喜欢Perl带来的函数式编程范例。用它编写一个列表应该是可行的,尽管有点挑战性,因为列表的长度是未知的 我缺少序列末尾的最后一个1,代码如下: use List::Gen '*'; iterate{ $_%2 ? 3*$_+1 : $_/2 }->from( 23 )->while( '!=1' )->say; 其中打印: 23 70 35 106 53 160 80 40 20 10 5 16 8 4 2 这种方法基本上需要的是边做边做。文档中提到了while,这是wh

我喜欢Perl带来的函数式编程范例。用它编写一个列表应该是可行的,尽管有点挑战性,因为列表的长度是未知的

我缺少序列末尾的最后一个
1
,代码如下:

use List::Gen '*';
iterate{ $_%2 ? 3*$_+1 : $_/2 }->from( 23 )->while( '!=1' )->say;
其中打印:

23 70 35 106 53 160 80 40 20 10 5 16 8 4 2
这种方法基本上需要的是
边做边做。文档中提到了
while
,这是
while
的一个“前瞻”版本,但口译员找不到这样的方法。

这是可行的(首先):

让我看看我是否能用它做一个函数,并使
$delay
安全

这应该可以工作,但不能工作,因为传递到
的函数在调用两次之前(第一个值除外)被调用:

这适用于双函数调用:

use List::Gen '*';
sub after { use feature 'state'; $f = shift(); $f = '$_' . $f unless (ref($f)); sub { state($d1,$d2); $r = $d2; $d2 = $d1; $d1 = eval $f; $r } }
iterate{ $_%2 ? 3*$_+1 : $_/2 }->from( 23 )->until(after('==1'))->say;
仍在试图理解为什么在第一次调用后调用了两次
until
函数

它仅适用于
期间,而不适用于
期间

上面的代码只适用于字符串参数;此选项适用于函数引用:

#!/usr/bin/perl
use strict;
use List::Gen '*';

sub after {
        use feature 'state';
        my $f = shift();
        my $c = ref($f) eq 'CODE'
                        ? '&$f()'
                        : '$_' . $f;
        sub {
                state($d1,$d2);
                my $r = $d2;
                $d2 = $d1;
                $d1 = eval($c);
                $f;
                $r
        }
}
iterate{$_%2 ? 3*$_+1 : $_/2}->from(23)->until(after('==1'))->say;
iterate{$_%2 ? 3*$_+1 : $_/2}->from(23)->until(after(sub{$_ == 1}))->say;

下面是一个变通方法,用于测试元素的
定义
-ness,以决定何时结束列表。它需要修改迭代器定义,以便在链中遇到
1
后立即填充
undef
元素:

iterate{ $_ == 1 ? undef : $_%2  ? 3*$_+1 : $_/2 }->from( 23 )->while( 'defined' )->say;
哪张照片

23 70 35 106 53 160 80 40 20 10 5 16 8 4 2 1

隐马尔可夫模型。。。有一个很好的函数,但是发现在第一次
while
直到调用之后,随后的
while
直到对相同的值执行两次调用:即23、70、70、35、35、106、106、…、4、4、2、2、1!请参阅:
iterate{$\u%2?3*$\u1:$\u2}->from(23)->而(sub{print“\=$\un”;$\u2!=1})->说
我找到了一个感觉更干净的方法,它包括在遇到第一个
1
后附加一个
undef
,并测试
定义的
-ness,如果不是为了双重调用(这仍然让我困惑),我可以让这个延迟函数返回额外的序列,这些序列可能对非终止序列有用。
iterate{ $_ == 1 ? undef : $_%2  ? 3*$_+1 : $_/2 }->from( 23 )->while( 'defined' )->say;
23 70 35 106 53 160 80 40 20 10 5 16 8 4 2 1