Closures, anonymous subroutines

Closures are anonymous subroutines which reference lexical variables of a surrounding block and this way retain their values. Here is an example from the textbooks:

sub genanon
{
    my ($string) = @_; 
    return sub {print "$string\n"};
}

my $f1 = genanon( "Guten Tag"); 
my $f2 = genanon( "Hallo"); 

&$f1(); # prints 'Guten Tag'
&$f2(); # prints 'Hallo'

The variable $string is created, each time genanon is invoked. Normally lexical variables are deallocated when the surrounding function exits. But genanon creates a function that uses $string. This has the effect that the reference count to the value of $string does not reach zero when genanon returns. Hence $f1 and $f2 refer to subroutines that have some private piece of data.

Let's look at a more realistic example. Closures are best put into action as call-back routines for widgets. In the following example a menu button is created which allows the user to set a variable named $var. Each of the menu items select a specific value.

#!/usr/bin/perl -w
use strict;
use Tk 800.000;
use vars qw($var);

$var = 1;
my $w_top = Tk::MainWindow->new;

my $b = $w_top->Menubutton( -relief => 'raised', 
			    -text => "Button: $var")->pack();
foreach my $i qw( 1 2 5 10 20)
{
    $b->command( -label => "$i", 
		 -command =>  sub { 
		     $var = $i;
		     $b->configure( -text => "Button: $var")});
}
#
# exit button
# 
$w_top->Button( -relief => 'raised', 
		-text => "exit",
		-command => sub { $w_top->destroy();})->pack();
MainLoop;

Notice that $i is a lexical variable to the foreach loop block. Thus the anonymous functions which are assigned to the -command parameter contain private values of $i.

Closures are a bit confusing. To clarify things it may be instructive to modify the code in a way that it fails: replace 'use vars qw($var)' by 'use vars qw($var $i)' and 'my $i' by '$i' . Insert a '$i = 1234;' line before the loop. $i is turned into a global variable. All actions that are invoked by the button set $var to 1234.