How to create a closure in Perl?
Question
How to create a closure in Perl?
In Perl, a closure is a subroutine that captures variables from its enclosing lexical scope, allowing it to access and retain those variables even after the outer subroutine has finished executing. Closures are powerful for creating private state, callbacks, and deferred computations.
Understanding Closures in Perl
Perl’s closures work because of my variables (lexical variables) and how Perl’s subroutines keep a reference to their surrounding lexical environment if they “close over” it. When a subroutine is returned or stored in a variable, it still has access to those lexicals, retaining their current state.
This differs from global variables (like $GLOBALS or our variables) because those are not “captured.” Only lexical variables declared with my are closed over by anonymous subs.
Key Concepts
myvariables define lexical scope, crucial for closures.- A closure keeps references to lexicals even if the outer subroutine returns.
- Closures are typically created as anonymous subs (using
sub { ... }). - Different closures created inside the same subroutine maintain independent lexical environments.
Example: Creating and Using a Closure
This example defines a counter generator subroutine that returns a closure. Each closure maintains its own private count state.
#!/usr/bin/perl
use strict;
use warnings;
sub make_counter {
my $count = 0; # Lexical variable captured by closure
return sub {
$count++; # Modify lexical variable
return $count;
};
}
# Create two independent counters
my $counter1 = make_counter();
my $counter2 = make_counter();
print "Counter 1: ", $counter1->(), "\n"; # 1
print "Counter 1: ", $counter1->(), "\n"; # 2
print "Counter 2: ", $counter2->(), "\n"; # 1 (separate state)
print "Counter 1: ", $counter1->(), "\n"; # 3
print "Counter 2: ", $counter2->(), "\n"; # 2
Each call to make_counter creates a new lexical $count. The anonymous sub returned retains access to this $count variable and modifies it. Even though make_counter has finished running, its lexical variable survives within the closure.
Common Pitfalls and Gotchas
- Globals vs Lexicals: Using global variables (
ouror package variables) won't create true closures because they’re not lexically scoped. - Reference copying: Returning references to lexicals creates closures, but copying a subroutine with
*foo = \&bar;does not make closures. - Beware of loop variables: Capturing loop variables can cause unexpected behavior if the variable changes. Use
myinside the loop to create a new lexical for each iteration. - Perl versions: Basic closures have worked the same way since early Perl 5 versions. No special version requirements.
Summary
To create a closure in Perl:
- Define
mylexical variables in an outer scope. - Create and return an anonymous subroutine that refers to these lexicals.
- Call the returned subroutine. It retains access to the captured variables.
This programming pattern is elegant and powerful, enabling encapsulation and functional programming styles in Perl.
Verified Code
Executed in a sandbox to capture real output. • v5.34.1 • 7ms
Counter 1: 1
Counter 1: 2
Counter 2: 1
Counter 1: 3
Counter 2: 2
(empty)Was this helpful?
Related Questions
- How to use the return statement early in a Perl subroutine?
- How to create higher-order functions in Perl?
- How to use shift to get subroutine arguments in Perl?
- How to use caller() to get subroutine call information in Perl?
- How to call a subroutine as a method in Perl?
- How to use state variables in Perl subroutines?