Jun 22, 2008

Closure in Perl

What is closure?

- Anonymous subroutines (subroutines without name) act as closures with respect to my() variables ie., lexical variables.

- Closure says if you define an anonymous function in a particular lexical
context, it pretends to run in that context even when it's called outside of
the context.

Example:
########

#!F:\Perl\bin\perl -w
use strict;

sub newprint {
   my $x = shift; # 'x' is a lexical variable
   return sub { my $y = shift; print "$x, $y!\n"; }; #Anonymous subroutine, observe $x
}
my $h = newprint("Howdy");
my $g = newprint("Greetings");

&$h("world"); # Howdy world
&$g("earthlings"); # Greetings earthlings


Note particularly that $x continues to refer to the value passed into
newprint() despite the fact that the my $x has seemingly gone out of
scope by the time the anonymous subroutine runs. That's what closure is all
about.

This applies only to lexical variables, by the way. Dynamic variables
continue to work as they have always worked. Closure is not something that
most Perl programmers need trouble themselves about to begin with.


One More Example on Closure:
##########################

- The important thing about closures is that you can use them to hide different lexicals into seperate
references to the same subroutine.

- I think that the important thing about closures is being able to call the same code but have it use different
variables (without passing them in as arguments).


use strict;
sub make_hello_printer {
  my $message = "Hello, world!";
  return sub { print $message; }
}

my $print_hello = make_hello_printer();
$print_hello->()



As you'd expect, that prints out the Hello, world! message. Nothing special going on here, is there? Well,

actually, there is. This is a closure. Did you notice?

What's special is that the subroutine reference we created refers to a lexical variable called $message. The

lexical is defined in make_hello_printer, so by rights, it shouldn't be visible outside of make_hello_printer,

right? We call make_hello_printer, $message gets created, we return the subroutine reference, and then

$message goes away, out of scope.

Except it doesn't. When we call our subroutine reference, outside of make_hello_printer, it can still see and

receive the correct value of $message. The subroutine reference forms a closure, ``enclosing'' the lexical

variables it refers to.


One More Example on Closure:
##########################

#!F:\Perl\bin\perl -w
use strict;

sub make_counter {
my $start = shift;
return sub { $start++ }
}

my $from_ten = make_counter(10);
my $from_three = make_counter(3);
print $\ = "\n"; # Prints new line each and every print
print $from_ten->(); # 10
print $from_ten->(); # 11
print $from_three->(); # 3
print $from_ten->(); # 12
print $from_three->(); # 4

No comments:

Post a Comment