3

List::Gen我喜欢Perl 带来的函数式编程范式。用它编写一个Collat​​z 序列应该是可行的,尽管有点挑战,因为列表的长度是先验的。

我错过了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

这种方法我本质上需要的是一个do-while. 文档提到了 a while_,它是 的“前瞻”版本while,但解释器找不到这样的方法。

4

2 回答 2

1

这有效(作为开始):

use List::Gen '*';
iterate{$_%2 ? 3*$_+1 : $_/2}->from(23)->until(sub{$_ == 1 ? (($delay = 1), 0) : $delay})->say();

让我看看我是否可以从中制作一个功能并确保$delay安全...

这应该有效,但不能因为传递给的函数until被调用两次(第一个值除外):

use List::Gen '*';
sub after { use feature 'state'; $f = shift(); $f = '$_' . $f unless (ref($f)); sub { state $d; $r = $d; $d = eval $f; $r } }
iterate{ $_%2 ? 3*$_+1 : $_/2 }->from( 23 )->until(after('==1'))->say;

这适用于双重函数调用:

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在第一次调用后调用该函数两次。

它仅适用于until而不适用while

上面的代码只适用于字符串参数;这个适用于函数引用:

#!/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;
于 2015-06-04T21:12:04.103 回答
0

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

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
于 2015-06-05T10:35:56.050 回答