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).