When should I use the & to call a Perl subroutine?
I’m a frequent abuser of &
, but mostly because I’m doing weird interface stuff. If you don’t need one of these situations, don’t use the &
. Most of these are just to access a subroutine definition, not call a subroutine. It’s all in perlsub.
-
Taking a reference to a named subroutine. This is probably the only common situation for most Perlers:
my $sub = \&foo;
-
Similarly, assigning to a typeglob, which allows you to call the subroutine with a different name:
*bar = \&foo;
-
Checking that a subroutine is defined, as you might in test suites:
if( defined &foo ) { … }
-
Removing a subroutine definition, which shouldn’t be common:
undef &foo;
-
Providing a dispatcher subroutine whose only job is to choose the right subroutine to call. This is the only situation I use
&
to call a subroutine, and when I expect to call the dispatcher many, many times and need to squeeze a little performance out of the operation:sub figure_it_out_for_me { # all of these re-use the current @_ if( …some condition… ) { &foo } elsif( …some other… ) { &bar } else { &default } }
-
To jump into another subroutine using the current argument stack (and replacing the current subroutine in the call stack), an unrare operation in dispatching, especially in
AUTOLOAD
:goto ⊂
-
Call a subroutine that you’ve named after a Perl built-in. The
&
always gives you the user-defined one. That’s why we teach it in Learning Perl. You don’t really want to do that normally, but it’s one of the features of&
.
There are some places where you could use them, but there are better ways:
-
To call a subroutine with the same name as a Perl built-in. Just don’t have subroutines with the same name as a Perl built-in. Check perlfunc to see the list of built-in names you shouldn’t use.
-
To disable prototypes. If you don’t know what that means or why you’d want it, don’t use the
&
. Some black magic code might need it, but in those cases you probably know what you are doing. -
To dereference and execute a subroutine reference. Just use the
->
notation.