--- name: subroutine references --- # 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: ```perl 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: ```perl 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: ```perl $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: ```perl 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: ```perl 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: ```perl 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: ```perl 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: ```perl 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: ```perl 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`](../../p5/core/perlfunc/ref) on a code reference returns the string `CODE`: ```perl ref $cref # CODE ref \&greet # CODE ``` [`defined`](../../p5/core/perlfunc/defined) works as usual to tell "no value" from "any value, including a code reference": ```perl 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).