Perl 如何使用List::Gen编写Collatz序列?
我喜欢Perl带来的函数式编程范例。用它编写一个列表应该是可行的,尽管有点挑战性,因为列表的长度是未知的 我缺少序列末尾的最后一个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
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