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.