=head1 NAME
-perlfaq7 - General Perl Language Issues ($Revision: 1.23 $, $Date: 2005/04/07 21:39:34 $)
+perlfaq7 - General Perl Language Issues ($Revision: 8539 $)
=head1 DESCRIPTION
Closures are documented in L<perlref>.
I<Closure> is a computer science term with a precise but
-hard-to-explain meaning. Closures are implemented in Perl as anonymous
-subroutines with lasting references to lexical variables outside their
-own scopes. These lexicals magically refer to the variables that were
-around when the subroutine was defined (deep binding).
-
-Closures make sense in any programming language where you can have the
-return value of a function be itself a function, as you can in Perl.
-Note that some languages provide anonymous functions but are not
-capable of providing proper closures: the Python language, for
+hard-to-explain meaning. Usually, closures are implemented in Perl as
+anonymous subroutines with lasting references to lexical variables
+outside their own scopes. These lexicals magically refer to the
+variables that were around when the subroutine was defined (deep
+binding).
+
+Closures are most often used in programming languages where you can
+have the return value of a function be itself a function, as you can
+in Perl. Note that some languages provide anonymous functions but are
+not capable of providing proper closures: the Python language, for
example. For more information on closures, check out any textbook on
functional programming. Scheme is a language that not only supports
but encourages closures.
-Here's a classic function-generating function:
+Here's a classic non-closure function-generating function:
sub add_function_generator {
return sub { shift() + shift() };
$add_sub = add_function_generator();
$sum = $add_sub->(4,5); # $sum is 9 now.
-The closure works as a I<function template> with some customization
-slots left out to be filled later. The anonymous subroutine returned
-by add_function_generator() isn't technically a closure because it
-refers to no lexicals outside its own scope.
+The anonymous subroutine returned by add_function_generator() isn't
+technically a closure because it refers to no lexicals outside its own
+scope. Using a closure gives you a I<function template> with some
+customization slots left out to be filled later.
Contrast this with the following make_adder() function, in which the
returned anonymous function contains a reference to a lexical variable
hypothetical timeout() function to access the lexical variable
$line back in its caller's scope.
+Another use for a closure is to make a variable I<private> to a
+named subroutine, e.g. a counter that gets initialized at creation
+time of the sub and can only be modified from within the sub.
+This is sometimes used with a BEGIN block in package files to make
+sure a variable doesn't get meddled with during the lifetime of the
+package:
+
+ BEGIN {
+ my $id = 0;
+ sub next_id { ++$id }
+ }
+
+This is discussed in more detail in L<perlsub>, see the entry on
+I<Persistent Private Variables>.
+
=head2 What is variable suicide and how can I prevent it?
-Variable suicide is when you (temporarily or permanently) lose the
-value of a variable. It is caused by scoping through my() and local()
-interacting with either closures or aliased foreach() iterator
-variables and subroutine arguments. It used to be easy to
-inadvertently lose a variable's value this way, but now it's much
-harder. Take this code:
+This problem was fixed in perl 5.004_05, so preventing it means upgrading
+your version of perl. ;)
+
+Variable suicide is when you (temporarily or permanently) lose the value
+of a variable. It is caused by scoping through my() and local()
+interacting with either closures or aliased foreach() iterator variables
+and subroutine arguments. It used to be easy to inadvertently lose a
+variable's value this way, but now it's much harder. Take this code:
- my $f = "foo";
+ my $f = 'foo';
sub T {
while ($i++ < 3) { my $f = $f; $f .= "bar"; print $f, "\n" }
}
T;
print "Finally $f\n";
+If you are experiencing variable suicide, that C<my $f> in the subroutine
+doesn't pick up a fresh copy of the C<$f> whose value is <foo>. The output
+shows that inside the subroutine the value of C<$f> leaks through when it
+shouldn't, as in this output:
+
+ foobar
+ foobarbar
+ foobarbarbar
+ Finally foo
+
The $f that has "bar" added to it three times should be a new C<$f>
-(C<my $f> should create a new local variable each time through the loop).
-It isn't, however. This was a bug, now fixed in the latest releases
-(tested against 5.004_05, 5.005_03, and 5.005_56).
+C<my $f> should create a new lexical variable each time through the loop.
+The expected output is:
+
+ foobar
+ foobar
+ foobar
+ Finally foo
=head2 How can I pass/return a {Function, FileHandle, Array, Hash, Method, Regex}?
objects. See L<perlsub/"Pass by Reference"> for this particular
question, and L<perlref> for information on references.
-See "Passing Regexes", below, for information on passing regular
-expressions.
+See "Passing Regexes", later in L<perlfaq7>, for information on
+passing regular expressions.
=over 4
with lexical variables, though.
You can fake a static variable by using a lexical variable which goes
-of scope. In this example, you define the subroutine C<counter>, and
+out of scope. In this example, you define the subroutine C<counter>, and
it uses the lexical variable C<$count>. Since you wrap this in a BEGIN
block, C<$count> is defined at compile-time, but also goes out of
scope at the end of the BEGIN block. The BEGIN block also ensures that
sub counter { $count++ }
}
- my $start = count();
+ my $start = counter();
- .... # code that calls count();
+ .... # code that calls counter();
- my $end = count();
+ my $end = counter();
In the previous example, you created a function-private variable
because only one function remembered its reference. You could define
This is explained in more depth in the L<perlsyn>. Briefly, there's
no official case statement, because of the variety of tests possible
in Perl (numeric comparison, string comparison, glob comparison,
-regex matching, overloaded comparisons, ...).
-Larry couldn't decide how best to do this, so he left it out, even
-though it's been on the wish list since perl1.
+regex matching, overloaded comparisons, ...). Larry couldn't decide
+how best to do this, so he left it out, even though it's been on the
+wish list since perl1.
Starting from Perl 5.8 to get switch and case one can use the
Switch extension and say:
line in your perl script (the "shebang" line) does not contain the
right path to perl (or any other program capable of running scripts).
Sometimes this happens when you move the script from one machine to
-another and each machine has a different path to perl---/usr/bin/perl
+another and each machine has a different path to perl--/usr/bin/perl
versus /usr/local/bin/perl for instance. It may also indicate
that the source machine has CRLF line terminators and the
destination machine has LF only: the shell tries to find
your PATH, which might also mean that the location of perl is not
where you expect it so you need to adjust your shebang line.
+=head1 REVISION
+
+Revision: $Revision: 8539 $
+
+Date: $Date: 2007-01-11 00:07:14 +0100 (jeu, 11 jan 2007) $
+
+See L<perlfaq> for source control details and availability.
+
=head1 AUTHOR AND COPYRIGHT
-Copyright (c) 1997-2005 Tom Christiansen, Nathan Torkington, and
+Copyright (c) 1997-2007 Tom Christiansen, Nathan Torkington, and
other authors as noted. All rights reserved.
This documentation is free; you can redistribute it and/or modify it