Perl closures
last modified October 9, 2026
A closure is a subroutine that remembers the lexical variables that were in
scope when it was created. In Perl, every anonymous subroutine automatically
closes over the my variables surrounding its definition, and those
variables keep their values between calls even after the enclosing block has
finished running.
Closures turn subroutines into small objects with private state. They are used to build counters, sub factories, iterators, generators, callbacks, dispatch tables, and memoizing wrappers. In this tutorial we cover Perl closures with practical examples, from simple lexical capture to the gotchas that surprise beginners.
Anonymous subroutines and code references are the foundation of the topic; see the Perl references and Perl subroutines tutorials if those terms are new to you.
Lexical capture
The simplest closure is an anonymous subroutine that uses a variable declared outside itself. The subroutine keeps a reference to that variable, so the value stays reachable as long as the code reference exists.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
sub make_greeter {
my $greeting = "Hello";
my $name = "Perl";
my $greet = sub {
say "$greeting, $name!";
};
return $greet;
}
my $greeter = make_greeter();
$greeter->();
$greeter->();
When make_greeter returns, $greeting and
$name are no longer visible to the rest of the program, yet the
returned code reference still reads them on every call. The variable is not
copied into the subroutine; the subroutine holds a reference to the same
storage, which is why the value survives the lifetime of the enclosing block.
$ perl capture.pl Hello, Perl! Hello, Perl!
Why my matters
A closure only remembers variables it can capture. Lexicals declared with
my are captured, so each call to the enclosing subroutine gets a
fresh private variable. Package variables are not captured at all: they are
global, so every subroutine that mentions them shares the same storage.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
our $SHARED = 0;
sub bump_global {
$SHARED++;
return $SHARED;
}
my $g1 = \&bump_global;
my $g2 = \&bump_global;
say "global: ", $g1->(), " ", $g2->(), " ", $g1->();
sub make_counter {
my $n = 0;
return sub {
$n++;
return $n;
};
}
my $c1 = make_counter();
my $c2 = make_counter();
say "counter1: ", $c1->(), " ", $c1->();
say "counter2: ", $c2->();
say "counter1: ", $c1->();
Both $g1 and $g2 point at the same named subroutine,
so they walk the same global counter. The two closures are different: each call
to make_counter creates a new $n, so
$c1 and $c2 count independently. This is the property
that makes closures useful for holding private state.
$ perl my_vs_global.pl global: 1 2 3 counter1: 1 2 counter2: 1 counter1: 3
Sub factories
A factory is a subroutine that returns a specialized subroutine. Because the parameters of the factory are themselves lexicals, they become part of the closure, which lets one factory produce many variants of the same behaviour.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
sub make_counter {
my ($start, $step) = @_;
my $value = $start;
return sub {
my $current = $value;
$value += $step;
return $current;
};
}
sub make_accumulator {
my $total = 0;
return sub {
my ($amount) = @_;
$total += $amount;
return $total;
};
}
my $odds = make_counter(1, 2);
say "odds: ", join(" ", map { $odds->() } 1 .. 4);
my $acc = make_accumulator();
say "acc: ", $acc->(10);
say "acc: ", $acc->(5);
say "acc: ", $acc->(-3);
my $other = make_accumulator();
say "other: ", $other->(100);
make_counter captures both the start value and the step, so the
same code produces odd numbers, even numbers, or a countdown depending on the
arguments. make_accumulator captures a running total and takes its
argument at call time, which shows that a closure can combine remembered state
with new parameters. Note that $acc and $other never
interfere, because each factory call allocated a separate $total.
$ perl factories.pl odds: 1 3 5 7 acc: 10 acc: 15 acc: 12 other: 100
Iterators
An iterator is a closure that returns the next element of a sequence on each call and a false value when the sequence is exhausted. The position is kept inside the closure, so the caller needs no index variable.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
sub make_iterator {
my @items = @_;
my $index = 0;
return sub {
return undef if $index >= @items;
return $items[$index++];
};
}
my $iter = make_iterator("alpha", "beta", "gamma");
while (defined(my $item = $iter->())) {
say "item: $item";
}
my $again = make_iterator(1, 2, 3);
while (defined(my $n = $again->())) {
say "n: $n";
}
my $empty = make_iterator();
say "empty: ", defined $empty->() ? "has value" : "no more items";
The loop condition must test with defined, because a legitimate
element can be the empty string or the number 0, both of which are
false in boolean context. Declaring my $item inside the
while condition keeps the loop variable lexical. Each iterator owns
its own copy of @items and $index, so several
iterators can walk the same kind of sequence at the same time.
$ perl iterator.pl item: alpha item: beta item: gamma n: 1 n: 2 n: 3 empty: no more items
Generators
A generator is an iterator that computes its values instead of storing them. Because the state lives in the closure, an infinite or very large sequence costs nothing until values are actually requested.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
sub make_fib {
my ($a, $b) = (0, 1);
return sub {
my $value = $a;
($a, $b) = ($b, $a + $b);
return $value;
};
}
my $fib = make_fib();
say "fib: ", join(" ", map { $fib->() } 1 .. 10);
sub make_range {
my ($from, $to) = @_;
my $next = $from;
return sub {
return undef if $next > $to;
return $next++;
};
}
my $range = make_range(1, 5);
my $sum = 0;
while (defined(my $n = $range->())) {
$sum += $n;
}
say "sum 1..5 = $sum";
my $lazy = make_range(1, 1_000_000_000);
say "first three: ", join(" ", $lazy->(), $lazy->(), $lazy->());
make_fib keeps two numbers in the closure and shifts them on every
call, so the sequence grows without a stored list. make_range is
lazy: make_range(1, 1_000_000_000) returns immediately because
nothing is computed until the code reference is called. The same trick powers
line readers, tree walkers, and streaming parsers.
$ perl generator.pl fib: 0 1 1 2 3 5 8 13 21 34 sum 1..5 = 15 first three: 1 2 3
Closures as callbacks
A code reference is an ordinary scalar, so it can be passed to map,
grep, and sort. A closure used this way can carry
configuration, such as a threshold or a sort order, without extra global
variables.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
my @nums = (1 .. 10);
my $square = sub { $_[0] * $_[0] };
my @squares = map { $square->($_) } @nums;
say "squares: @squares";
my $is_even = sub { $_[0] % 2 == 0 };
my @evens = grep { $is_even->($_) } @nums;
say "evens: @evens";
my ($limit) = (5);
my $below = sub { $_[0] < $limit };
say "below $limit: ", join(" ", grep { $below->($_) } @nums);
my @words = qw(banana Apple cherry date);
my $by_length_then_alpha = sub {
return length($a) <=> length($b) || $a cmp $b;
};
my @sorted = sort { $by_length_then_alpha->() } @words;
say "sorted: @sorted";
Inside map and grep the current element is available as
$_, so the helper subroutines read their argument as
$_[0]. The sort closure relies on the special $a and
$b package variables, which sort localizes for the
duration of the block. The comparison first sorts by length and then falls back
to alphabetical order, which is why the uppercase Apple sorts before
the lowercase words of length five.
$ perl callbacks.pl squares: 1 4 9 16 25 36 49 64 81 100 evens: 2 4 6 8 10 below 5: 1 2 3 4 sorted: date Apple banana cherry
Dispatch tables
A hash of code references replaces a long if/elsif
chain with a lookup. Each entry is a closure that already captures whatever it
needs, and the handler is selected by name at run time.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
my %commands = (
add => sub { $_[0] + $_[1] },
subtract => sub { $_[0] - $_[1] },
multiply => sub { $_[0] * $_[1] },
max => sub { $_[0] > $_[1] ? $_[0] : $_[1] },
);
for my $request ([add => 3, 4], [subtract => 10, 4],
[multiply => 6, 7], [max => 9, 2]) {
my ($name, @args) = @$request;
if (my $handler = $commands{$name}) {
say "$name(@args) = ", $handler->(@args);
} else {
say "unknown command: $name";
}
}
my $missing = "divide";
say "unknown command: $missing" unless $commands{$missing};
my @known = sort keys %commands;
say "known commands: @known";
Values are taken from the hash and stored in $handler before the
call, and the existence test if (my $handler = ...) guards against
unknown names. That guard is required for a different reason than in some
languages: a hash of closures always evaluates to a true value when the key
exists, but calling an undefined entry would raise an error. Keys are sorted
before printing so that the output does not depend on hash ordering.
$ perl dispatch.pl add(3 4) = 7 subtract(10 4) = 6 multiply(6 7) = 42 max(9 2) = 9 unknown command: divide known commands: add max multiply subtract
Memoization
Memoization stores the result of a call and returns the cached value the next time the same arguments appear. A wrapper closure around the original subroutine keeps the cache private, so the caller sees no extra argument.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
my $calls = 0;
sub naive_fib {
my ($n) = @_;
$calls++;
return $n if $n < 2;
return naive_fib($n - 1) + naive_fib($n - 2);
}
sub memoize {
my ($func) = @_;
my %cache;
return sub {
my ($n) = @_;
return $cache{$n} if exists $cache{$n};
return $cache{$n} = $func->($n);
};
}
my $fib = memoize(\&naive_fib);
say "fib(20) = ", $fib->(20);
say "fib(30) = ", $fib->(30);
say "fib(20) again = ", $fib->(20);
say "underlying calls = $calls";
The wrapper captures %cache and the original code reference. The
test uses exists rather than a truth check, so a stored
0 would still be returned from the cache instead of recomputed. The
final counter shows that the exponential recursion still runs over two million
times in total, but every distinct argument is evaluated only once.
$ perl memoize.pl fib(20) = 6765 fib(30) = 832040 fib(20) again = 6765 underlying calls = 2714428
state variables versus closure state
Since Perl 5.10, a variable declared with state inside a named
subroutine is initialized once and then keeps its value between calls. It gives
a single named subroutine persistent private state, without wrapping it in a
factory.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
sub next_state {
state $count = 0;
return ++$count;
}
sub make_counter {
my $count = 0;
return sub { return ++$count };
}
my $c1 = make_counter();
my $c2 = make_counter();
say "state calls: ", next_state(), " ", next_state(), " ", next_state();
say "closure c1: ", $c1->(), " ", $c1->();
say "closure c2: ", $c2->();
say "state again: ", next_state();
state is the right tool when one subroutine needs one private
variable and there is only ever a single instance of it. A closure factory is
better when you need independent instances, as with $c1 and
$c2 above, or when the state must be created at an arbitrary point
in the program. In short: use state for singletons, use closures for
instances.
$ perl state.pl state calls: 1 2 3 closure c1: 1 2 closure c2: 1 state again: 4
The classic for loop closure bug
A C-style for loop declares one variable that is reused on every
iteration. If each iteration creates a closure over that variable, all the
closures see the same storage and therefore the final value.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
my @buggy;
for (my $i = 1; $i <= 3; $i++) {
push @buggy, sub { return $i };
}
say "shared loop variable: ", join(" ", map { $_->() } @buggy);
my @fixed;
for (my $i = 1; $i <= 3; $i++) {
my $copy = $i;
push @fixed, sub { return $copy };
}
say "fresh copy per iteration: ", join(" ", map { $_->() } @fixed);
sub make_adder {
my ($n) = @_;
return sub { return $_[0] + $n };
}
my @adders = map { make_adder($_) } 1 .. 3;
say "adders over 10: ", join(" ", map { $_->(10) } @adders);
my @foreach_cbs;
for my $n (1 .. 3) {
push @foreach_cbs, sub { return $n };
}
say "foreach my: ", join(" ", map { $_->() } @foreach_cbs);
Every closure in @buggy shares $i, which has already
been incremented to 4 when the closures are finally called. There
are two standard fixes: copy the value into a fresh my variable
inside the loop, or move the loop body into a factory such as
make_adder. The last loop shows that the list form
for my $n (1 .. 3) creates a fresh variable per iteration in modern
Perl, so it does not show the bug; only the C-style loop does.
$ perl loop_bug.pl shared loop variable: 4 4 4 fresh copy per iteration: 1 2 3 adders over 10: 11 12 13 foreach my: 1 2 3
Capturing $_ and @_ aliasing
Two built-in variables behave in ways that surprises closure writers: $_
is a package variable, so a closure that reads it does not capture a private
copy, and @_ holds aliases to the caller's arguments, so writing to
$_[0] modifies the caller's variable.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
my @nums = (1 .. 5);
my @doubled = map { my $n = $_; sub { return $n * 2 } } @nums;
say "captured copies: ", join(" ", map { $_->() } @doubled);
my @readers = map { sub { return defined($_) ? $_ : "undefined" } } 1 .. 3;
$_ = "outer";
my @seen;
for my $reader (@readers) {
push @seen, $reader->();
}
say "read global \$_ later: @seen";
sub shout {
$_[0] = uc $_[0];
return $_[0];
}
my $word = "quiet";
my $loud = shout($word);
say "argument after call: $word";
say "returned: $loud";
The first group copies $_ into a lexical, so each closure keeps its
own number. The second group does not: the closures read the global
$_ at call time, and after it is set to "outer" all
three return that value. The shout subroutine demonstrates aliasing:
assigning to $_[0] rewrites the caller's $word. Unpack
@_ into lexicals with my ($x) = @_; whenever the
arguments should be private to the subroutine.
$ perl capture_gotchas.pl captured copies: 2 4 6 8 10 read global $_ later: outer outer outer argument after call: QUIET returned: QUIET
Captured variables keep their referents alive
A closure holds a real reference to every lexical it captures, which keeps the captured value and anything it points to alive. When the closure is discarded, the reference count drops to zero and the object is destroyed.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
my @destroyed;
sub new_handle {
my ($id) = @_;
return bless { id => $id }, "Handle";
}
sub make_probe {
my ($id) = @_;
my $handle = new_handle($id);
return sub { return "probing " . $handle->{id} };
}
package Handle;
sub DESTROY {
my ($self) = @_;
push @destroyed, $self->{id};
return;
}
package main;
my $probe = make_probe(1);
say $probe->();
say "after factory returns: [@destroyed]";
my $temporary = make_probe(2);
undef $temporary;
say "after undef: [@destroyed]";
{
my $scoped = make_probe(3);
say $scoped->();
}
say "after scope exit: [@destroyed]";
say "still probing: ", $probe->();
The handle created for the first probe is still reachable through
$probe, so releasing the factory does not free it. Delegating the
code reference with undef drops the last reference and destroys the
handle immediately; leaving the block does the same for the third probe. This is
why a closure over a large data structure can look like a memory leak: the data
is only released when the last code reference that captured it disappears.
Modules such as Scalar::Util can inspect reference counts and
addresses, but printing them is never done in examples because the values differ
between runs.
$ perl refcount.pl probing 1 after factory returns: [] after undef: [2] probing 3 after scope exit: [2 3] still probing: probing 1
Closures versus objects
A closure with state and an object with a method solve the same problem in different ways. The closure hides its data completely and is created with a single call; the object exposes its fields, supports inheritance, and can carry many methods.
#!/usr/bin/perl
use strict;
use warnings;
use v5.34.0;
sub make_counter {
my $count = 0;
return sub { return ++$count };
}
package Counter;
sub new {
my ($class) = @_;
return bless { count => 0 }, $class;
}
sub next {
my ($self) = @_;
return ++$self->{count};
}
package main;
my $closure = make_counter();
my $object = Counter->new();
say "closure: ", $closure->(), " ", $closure->();
say "object: ", $object->next(), " ", $object->next();
say "object field is reachable: ", $object->{count};
Both counters behave identically, but the closure offers no public field: the
only way to change $count is to call the code reference. The object
stores its state in a hash, which any code can read or overwrite, but it can be
extended with more methods, serialized, or blessed into a subclass. A common
rule of thumb is to use a closure for a single small behaviour and a class as
soon as the data needs a name, documentation, or more than one operation.
$ perl closure_vs_object.pl closure: 1 2 object: 1 2 object field is reachable: 2
In this article we have covered Perl closures: lexical capture, the difference
between my variables and globals, sub factories, iterators,
generators, callbacks, dispatch tables, memoization, state
variables, the classic loop bug, built-in variable gotchas, reference lifetime,
and the relationship to objects. Together these techniques let you attach
private state to subroutines without adding global variables to your programs.
Best Practices
- Capture lexicals, not globals: declare the state with
myinside the enclosing subroutine so each closure gets its own copy instead of sharing a package variable. - Use a factory for instances: return closures from a subroutine when you need independent counters, iterators, or handlers; reserve
statefor a single private value inside one named subroutine. - Guard iterators with
defined: testwhile (defined(my $x = $iter->())), because0and the empty string are valid values that are false in boolean context. - Never capture a reused loop variable: copy the value into a fresh
myinside the loop or move the body into a factory when the loop variable is declared once, as in a C-stylefor. - Unpack
@_and copy$_: assign arguments to lexicals before use, since@_holds aliases to the caller's variables and$_is a global that can change after a closure is created. - Mind what a closure keeps alive: a code reference holds every captured value, so drop large wrappers with
undefwhen they are no longer needed and avoid capturing whole data structures needlessly.
Source
Perl subroutines · Perl references and nested data structures · Perl FAQ, subroutines and closures · Perl syntax, state variables · The state keyword · Perl objects · Scalar::Util · List::Util
Author
List all Perl tutorials.