Subroutine references#
A subroutine reference is a scalar that points at a piece of code. Once you have one, you can store it in a variable, pass it to another subroutine as a callback, keep a table of them for dispatch, or call it. Code references are what make dispatch tables, callbacks, iterators, and closures possible in Perl.
Two ways to get a code reference#
\&name — take a reference to a named subroutine:
sub greet { print "hello $_[0]\n" }
my $cref = \&greet;
$cref->('world'); # hello world
The & sigil is what marks greet as a subroutine. The backslash
in front takes its reference. Without the &, you’d be calling
the subroutine and taking a reference to the result.
sub { ... } — an anonymous subroutine. It evaluates to a
reference to a fresh, nameless piece of code:
my $cref = sub { print "hello $_[0]\n" };
$cref->('world');
Anonymous subs are the direct analogue of [...] and {...} from
the previous chapter: a constructor that gives you back a reference
to something new and nameless.
Calling through a reference#
$cref->(@args) is the one you reach for:
$cref->('world');
$cref->($x, $y);
$cref->(); # call with no arguments
There is also an older syntax, &{$cref}(...), parallel to the
@{$aref} / %{$href} form. It’s still valid but the arrow form
is standard everywhere modern.
Inside the called subroutine, arguments arrive in @_ as usual:
my $max = sub {
my ($a, $b) = @_;
$a > $b ? $a : $b;
};
print $max->(3, 7); # 7
Callbacks — passing code to another routine#
Any subroutine that takes a code reference can accept either a named-subroutine reference or an anonymous one:
sub each_line {
my ($filename, $cb) = @_;
open my $fh, '<', $filename or die "$filename: $!";
while (my $line = <$fh>) {
$cb->($line);
}
}
# Pass a named sub:
sub print_upper { print uc $_[0] }
each_line('notes.txt', \&print_upper);
# Or an anonymous one, inline:
each_line('notes.txt', sub { print uc $_[0] });
Inline anonymous subs are the idiomatic form when the callback body is short and specific to the call site.
Dispatch tables#
A hash of code references replaces long if / elsif chains:
my %dispatch = (
help => sub { print "usage: tool [cmd]\n" },
list => sub { print "$_\n" for @items },
quit => sub { exit 0 },
);
my $cmd = shift @ARGV;
if (my $action = $dispatch{$cmd}) {
$action->();
} else {
die "unknown command: $cmd\n";
}
Each value in %dispatch is a code reference. Looking up by
command name and calling through the reference replaces branching
with a single lookup. Adding a new command is a single hash entry.
Closures — code that captures lexicals#
An anonymous subroutine that references a lexical (my) variable
from its surrounding scope captures that variable. The
variable survives for as long as the subroutine reference does,
and each call sees the current value:
sub make_counter {
my $n = 0;
return sub { ++$n };
}
my $a = make_counter();
my $b = make_counter();
print $a->(); # 1
print $a->(); # 2
print $b->(); # 1 — independent from $a
print $a->(); # 3
Each call to make_counter creates a new lexical $n and a
new anonymous subroutine that captures that $n. The
subroutine returned to $a and the one returned to $b close
over distinct variables, so their counters don’t interfere.
This is how Perl expresses most of what other languages call “objects with private state” without any class machinery: the closed-over lexicals are the private state.
A closure captures by reference, not by copy. A loop like this captures the same loop variable:
my @subs;
for my $i (1 .. 3) {
push @subs, sub { print "i=$i\n" };
}
$_->() for @subs; # i=1 / i=2 / i=3
…because my $i in for my $i is re-my’d on every iteration,
so each closure captures a different $i. The common mistake
is using a for-loop variable that isn’t my’d freshly:
my $i; # outer
my @subs;
for $i (1 .. 3) {
push @subs, sub { print "i=$i\n" };
}
$_->() for @subs; # i=3 / i=3 / i=3 — all share the outer $i
The fix is for my $i (...) — always prefer the inline my.
Introspection#
ref on a code reference returns the
string CODE:
ref $cref # CODE
ref \&greet # CODE
defined works as usual to tell
“no value” from “any value, including a code reference”:
if (defined $dispatch{$cmd}) { ... }
Where to go next#
Weak references — relevant when a structure of code references holds references back to objects that own it (event emitters, observer chains).