#! /usr/bin/perl # higher-order functions in perl # in perl, "scalar" variables which include things like integers and # pointers, are always prefixed with a $. # in perl, "sub" means lambda. Instead of specifying the formal parameters # like in other languages, the parameters are always in an array, which # can be accessed inside the function body as $_[0], $_[1], etc ... # The entire array can be referred to as @_ # A perl function body always returns the last expression it evaluates. # "my" in perl is equivalent to "let" in scheme. # in perl, to apply a function that's returned from another function call, # we can use one of two forms. Assume that $f, $g, and $h are all # pointers to functions. The following are equivalent # &{&$f($g)}($h) and $f->($g)->($h) # both expressions are equivalent to ((f g) h) in scheme. The -> # operator is not the same as the -> in C/C++, but it's similar: # it dereferences a pointer, which in the case of Perl, can be a function. # Goto this link to learn more: # http://iis1.cps.unizar.es/Oreilly/perl/advprog/ch04_01.htm # the following is (lambda (x) (* 2 x)): sub twox { 2 * $_[0]; # $_[0] is first parameter } # function to map a function over a perl "array" # array variables are prefixed with @ instead of $ sub mapfun { my(@rlist); # list to be returned - look ma, no malloc! my($fun,@list) = @_; for ($i=0;$i<=$#list;$i++) { $rlist[$i] = $fun->($list[$i]); } # for loop @rlist; } # fold a (associative) binary operator over a list sub foldop { my($fun,$l,$id) = @_; # give names to parameters. my $answer = $id; # value to be returned my @list = @$l; # dereferences pointer to a list for ($i=0;$i<=$#list;$i++) { $answer = $fun->($list[$i],$answer); } $answer; # returns answer } # test code: @m = &mapfun(sub{$_[0]*$_[0]}, (2,3,5,7)); foreach (@m) {print $_, ' ';} print "\n"; # prints array elements @m = &mapfun(\&twox,@m); foreach (@m) {print $_, ' ';} print "\n"; # prints array elements print &foldop(sub{$_[0]*$_[1]},\@m,1), "\n"; # in the above call, \@m is a pointer to m