P is for Practical PerlMonks

Comment on

 Need Help??
The topic of lazy code came up recently in regards to Perl6. But with a little extra effort, we can do lazy lists in Perl5. So I thought I present a little taste of my favorite use for laziness: infinite lists...
```#!/usr/bin/perl

#make a finite lazy list (1,2,12,3.14)
\$g=cons(1,cons(2,cons(12,cons(3.14,undef))));

#double the values
\$twice = lazyMap(sub{2*\$_[0]}, \$g);

#print values to check correctness...
#should be 2,4,24,6.28
#don't try unlazyMap on infinite lists...
print "twice: ",join(",", unlazyMap(sub{\$_[0]}, \$twice))."\n";

\$z = zeros();    #create infinite list of zeros (a la /dev/zero)
\$inf=cons(3,\$z); #a infinite list of zeros with a 3 on the front

\$double_plus1 = lazyMap(sub{2*\$_[0]+1}, \$inf);
\$take8 = take(8, \$double_plus1); #grab first 8 values of infinite list
print "double_plus1: ",join(",", unlazyMap(sub{\$_[0]}, \$take8))."\n";

\$nums  = take(10, nums());
print "integers: ",join(",", unlazyMap(sub{\$_[0]}, \$nums))."\n";

\$fibs  = take(10, fibs(1,0));
print "fibs: ",join(",", unlazyMap(sub{\$_[0]}, \$fibs))."\n";
print "1000th Fibonacci: ",Nth(1000,fibs(1,0)),"\n";

\$primes  = take(10, primes(3,2));
print "primes: ",join(",", unlazyMap(sub{\$_[0]}, \$primes))."\n";

sub zeros { sub{ (0,zeros()) } }
sub nums  { sub{ (0, sub{ (1, lazyMap(sub{\$_[0]+2},nums())) })}}
sub fibs  { my (\$x, \$y)=@_; sub{ (\$x+\$y, fibs(\$y,\$x+\$y)) } }

sub primes{ my (\$n, @ps) = @_;
(scalar grep !(\$n % \$_), @ps)
? primes(\$n+2,@ps)
: sub{ (\$n, primes(\$n+2,\$n,@ps)) } }

###### Helper subroutines ###############
sub cons  { my (\$val, \$list) = @_;
sub { return (\$val, \$list) } }

sub head  { my (\$h, \$t)=\$_[0]->() if defined(\$_[0]);
return \$h;                               }

sub tail  { my (\$h, \$t)=\$_[0]->() if defined(\$_[0]);
return \$t;                               }

sub unlazyMap{  my (\$f, \$list) = @_;
my (\$h, \$t) = \$list->() if defined(\$list);

defined(\$t) ? (\$f->(\$h),unlazyMap(\$f,\$t))
:  \$f->(\$h)                   }

sub lazyMap {  my (\$f, \$list) = @_;
my (\$h, \$t) = \$list->() if defined(\$list);

defined(\$t)  ? sub{ (\$f->(\$h),lazyMap(\$f,\$t)) }
: sub{ (\$f->(\$h),undef         ) }    }

sub take  {  my (\$n, \$list) = @_;
return undef if (\$n <= 0 or !defined(\$list));
(my \$h, my \$t) = \$list->();
sub{ (\$h, take(\$n-1, \$t)) }                   }

sub Nth   {  my (\$n, \$list) = @_;
return undef if (!defined(\$list));
(my \$h, my \$t) = \$list->();
\$n<=1 ? \$h : Nth(\$n-1, \$t);        }

-- All code is 100% tested and functional unless otherwise noted.

In reply to Infinitely Lazy by sleepingsquirrel

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

• Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
• Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
• Read Where should I post X? if you're not absolutely sure you're posting in the right place.
• Posts may use any of the Perl Monks Approved HTML tags:
a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
• You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
 For: Use: & & < < > > [ [ ] ]
• Link using PerlMonks shortcuts! What shortcuts can I use for linking?

Create A New User
Chatterbox?
and a soft breeze sighs...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (4)
As of 2017-08-23 12:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
Who is your favorite scientist and why?

Results (350 votes). Check out past polls.

Notices?