I love the functional-programming paradigm that List::Gen brings to Perl. Writing a Collatz sequence with it should be doable, albeit a little challenging since the length of the list is not known a priori.
I'm missing the final 1 at the end of the sequence with the following code:
use List::Gen '*';
iterate{ $_%2 ? 3*$_+1 : $_/2 }->from( 23 )->while( '!=1' )->say;
which prints:
23 70 35 106 53 160 80 40 20 10 5 16 8 4 2
What I essentially need with this approach is a do-while. The documentation makes mention of a while_, which is a 'look-ahead' version of while, but the interpreter cannot find such a method.
This works (as a start):
use List::Gen '*';
iterate{$_%2 ? 3*$_+1 : $_/2}->from(23)->until(sub{$_ == 1 ? (($delay = 1), 0) : $delay})->say();
Let me see if I can make a function out of that and make $delay safe...
This should work, but doesn't because the function passed to until is called twice (except for the first value):
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;
This works for the double function call:
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;
Still trying to understand why the until function is called twice after the first call.
It works only for until and not while.
The code above only works with string arguments; this one works with function references:
#!/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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With