2015-05-29 58 views
3

我喜歡List::Gen帶給Perl的函數式編程範例。用它寫一個Collatz sequence應該是可行的,儘管有點難度,因爲列表的長度並不知道先驗。如何用List :: Gen編寫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。該文檔提到了一個while_,這是一個「向前看」版本while,但解釋器找不到這種方法。

回答

0

下面是測試元素defined -ness來決定何時結束列表中的解決方法。它需要修改定義迭代器立即填充一個undef元素遇到的鏈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 
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; 
+0

嗯...有一個很好的功能,但發現後對於相同的值,第一個「while」或「until」調用,隨後的「while」或「until」調用被執行兩次:即23,70,70,35,35,106,106,...,4,4, 2,2,1!參見:'iterate {$ _%2?從(23) - > while(sub {print「_ = $ _ \ n」; $ _!= 1}) - > say;' – kjpires

+0

我想通了,3 * $ _ + 1:$ _/2} - >一個[解決方法](http://stackoverflow.com/a/30664416/133939)感覺更清潔,其中包括在遇到第一個'1'後追加'undef'並測試'defined' -ness – Zaid

+0

如果它不是'對於雙重調用(仍然讓我感到困惑),我可以讓這個延遲函數返回N個附加序列,這對於非終止序列可能是有用的。 – kjpires