Saturday, 1 February 2014

Perl is Cool 1: First Class Functions

Last months at work I've been doing Perl, Perl and more Perl, and honestly, it sounds pretty much better than you could think. I already gave my first impressions here. The language is full of idioms that I don't like at all, as on one side they are not particularly useful and on the other side they're so alien to any other language that make code pretty hard to understand. Nevertheless, it has most (and sometimes much more, ie, multiple inheritance and AUTOLOAD) of the features that you would expect in a modern, decent language. This is the first (and very basic) installment in (maybe) a series of entries about "The Good Parts" of Perl.

As already mentioned in that previous entry, JavaScript draws much influence from Perl, and Functions (yes, I know the Perl word for this is "subroutines", but I'll call them functions) is one of the clear areas were any JavaScripter will feel mainly at home. Perl sports First Class Functions (that is, you can create Higher Order Functions), meaning that you can pass functions around and create and return them.

We have Named functions

sub doBeep{
 my ($name) = @_;
 say "doBeep: " . $name;
}

We can pass these functions to other functions, the only thing to take into account is that you don't pass around functions, but references to functions (yeah, having to waste brain cycles in thinking whether something is "a something" or "a reference to that something" stinks to old, awful C++). So you'll have to do this:

#I have a reference to a function here
my $doBeepRef = \&doBeep;
testCallback($doBeepRef);

As we're passing a reference to a function, you'll have to dereference it to invoke it, which can be done in these 2 ways:

sub testCallback{
 my $callback = shift;
 print "testing callback\n";
 #so to invoke it I have to dereference it, either this way:
 $callback->("yup");
 #or this way:
 &{$callback}("yup");
}

We also have anonymous functions. When declared we already get a reference to a function. We can declare them in an assignment, as a parameter or as a return:

my $callback = sub{ 
 #whatever
};

testCallback(sub{
 #whatever
});

sub functionFactory{
 return sub{
  #whatever
 };
)

Anonymous functions are particularly useful cause Perl has Closures:

sub wrapString{
 my ($wrapper, $str) = @_;
 return $wrapper . $str . $wrapper;
}

sub wrapperFactory{
 my $wrapper = shift;
 return sub{
  return wrapString($wrapper, @_);
 }
}

my $underscoreWrapper = wrapperFactory('_');
print $underscoreWrapper->("hi") . "\n";

The normal use of closures in Perl is the same as in other languages, but I don't know how they are implemented internally (in JavaScript you have the [[scope]] thing, in C# and Groovy the compiler creates extra classes under the covers, so I'm not sure about how they behave in more complex scenarios. This document explains some oddities.

Update, 2014-02-07 I forgot to mention that Perl has the equivalent to JavaScript's Immediately invoked function expressions (IIFEs). Let's see an example creating a closure:

my $printWithCounter = sub{
	my $counter = 0;
	return sub{
		print "printing for time " . $counter++ . "\n";
	}
}->();

for my $i (1..5){
	$printWithCounter->();
}

No comments:

Post a Comment