Declaration#

Every sub is one of three things: a named sub bound to a package, an anonymous sub stored in a code reference, or a lexical sub bound to a my-like slot in the current scope. The declaration form picks one; everything else (prototype, signature, attributes, body) decorates it.

Named subs#

sub greet {
    my ($name) = @_;
    return "Hello, $name!";
}

greet("Alice");                  # "Hello, Alice!"

The name greet is bound in the current package’s symbol table under the slash & slot — the same slot the runtime looks up when you call greet(...) or \&greet. Named subs are visible to any code that runs after the sub statement is compiled; in practice «compiled» means «the file is parsed up to the declaration», which is almost always what you want.

A named sub can also be declared in two parts — a forward declaration and a definition:

sub later;                       # promise: a sub named 'later' will exist
sub later {                      # fulfilment
    return 42;
}

The forward declaration is mainly useful when prototypes need to take effect for recursive calls (the prototype must be visible before the recursive call is parsed) or when you want to suppress «Bareword not allowed» warnings for code that calls the sub before its definition.

Calling a sub by name#

greet("Alice");                  # most common form
greet "Alice";                   # parens optional once predeclared
&greet("Alice");                 # legacy: disables prototype checking
&greet;                          # legacy: pass current @_ as the call's @_

The bare-& form (&greet with no parens) is a holdover from perl4 with one remaining legitimate use: passing the current @_ straight through without copying. See recursion for goto &greet, the tail-call variant.

Anonymous subs#

my $double = sub {
    my ($x) = @_;
    return $x * 2;
};

$double->(7);                    # 14

The sub { ... } expression evaluates to a code reference. It captures any lexical (my/state) variables from its enclosing scope — see scoping — and is invoked through ->() or with the legacy &$double() / &{$double}() forms.

Anonymous subs are how every Perl callback works:

my @sorted = sort { $a <=> $b } @list;
my @big    = grep { $_ > 100   } @list;
my @str    = map  { "<$_>"     } @list;

They are also the building block for closures, dispatch tables, and mock objects. A dispatch table:

my %op = (
    add => sub { $_[0] + $_[1] },
    sub => sub { $_[0] - $_[1] },
    mul => sub { $_[0] * $_[1] },
);

my $result = $op{$cmd}->($x, $y);

Code references#

A code reference is a first-class scalar that holds a sub. You get one from sub { ... }, from \&named_sub, or from a method lookup with can:

my $cref = \&greet;              # ref to named sub
my $cref = sub { ... };          # anonymous
my $cref = $obj->can('method');  # method lookup, returns code ref or undef

$cref->("Alice");                # invocation
&$cref("Alice");                 # legacy invocation

Inside a code ref, the sub keeps its identity: \&greet is always the same ref for the lifetime of the package’s &greet. Anonymous subs are distinct refs every time the sub { ... } expression is evaluated — that is what makes closure factories work.

Lexical subs#

A lexical sub is declared with my sub (and the corresponding state sub and our sub):

sub outer {
    my sub helper {
        my ($x) = @_;
        return $x * 2;
    }

    return helper(21);           # 42
}

helper(1);                       # error: undefined subroutine
                                 # (helper isn't visible here)

my sub is most useful inside long functions where you want a private helper without polluting the package namespace. It is not heavily used in the wild, but it is the proper tool when you want true encapsulation. See scoping for state and our variants.

Predeclaration#

A predeclaration is a sub NAME; statement (no body, no braces). Three reasons to write one:

# 1. Allow the sub to be called without parens before it's defined
sub later;
later;                           # parses as later()

# 2. Make a prototype visible before the body is reached
sub mypush (\@@);
sub mypush (\@@) { ... }

# 3. Document an exported API at the top of the file
sub greet;
sub farewell;
sub welcome;
# ... actual definitions further down

In modern code reasons (1) and (3) are mostly stylistic. Reason (2) is a real requirement when you use prototypes; see prototypes.

What you cannot do#

  • You cannot redefine a built-in by sub print { ... } and have Perl quietly use yours. Built-in overriding goes through CORE::GLOBAL::print and is documented under attributes and the prototype detail page.

  • You cannot have two named subs with the same name in the same package without a «Subroutine NAME redefined» warning. Either rename or genuinely intend the redefinition (and silence the warning with no warnings 'redefine';).

  • You cannot give a forward declaration and a body with different prototypes. The two declarations must agree.

See also#

  • Arguments and @_ — what the body sees once the call is made.

  • Scoping — what my, our, local, and state do to the variables inside the body.

  • sub — the keyword’s perlfunc page.

  • prototype — runtime introspection of a sub’s prototype, and the bridge to overriding built-ins.

  • Arrow operator->() invocation of code references.