#!/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); }