Misc

prototype#

Return the prototype string of a subroutine, or undef if it has none.

prototype inspects a subroutine and gives back the prototype the parser will use when compiling calls to it. FUNCTION is either a name (bareword or string) or a code reference. With no argument, the subroutine named by $_ is looked up. A CORE:: prefix asks for the prototype-equivalent of a core built-in.

Prototypes are the old compile-time parsing hints declared with sub foo ($$@) { ... }. They control how the parser shapes calls — they are not subroutine signatures (sub foo ($x, $y) { ... }), which are a separate feature that prototype does not report on.

Synopsis#

prototype FUNCTION
prototype
prototype \&foo
prototype 'Some::Package::foo'
prototype 'CORE::push'

What you get back#

A string describing the prototype, or undef when:

  • the subroutine exists but has no prototype declared, or

  • the name resolves to a CORE:: built-in whose argument shape the prototype mini-language cannot express (for example system, print, sort).

The string is exactly the text that appeared between the parentheses in the sub declaration, canonicalised: whitespace removed, each character one of the prototype letters below.

Character

Meaning in the prototype

$

one scalar argument

@

list — absorbs all remaining arguments

%

hash — absorbs all remaining arguments as a list

&

code block or code reference

*

typeglob or bareword treated as one

\$ \@ \% \& \*

reference to a scalar / array / hash / code / glob (caller writes @ary, callee receives \@ary)

\[...]

reference where any of the bracketed sigils is accepted

+

array or hash, passed by reference automatically

_

scalar that defaults to $_ if omitted

;

subsequent arguments are optional

A leading & with no parentheses after it, as in sub f (&@) { ... }, is what lets map, grep and sort-lookalikes take a block without a comma.

Global state it touches#

prototype with no argument reads $_ as the subroutine name. No other globals are consulted or modified.

Examples#

Read a user-defined prototype:

sub add ($$)   { $_[0] + $_[1] }
print prototype 'add';                  # $$
print prototype \&add;                  # $$

A sub with no prototype returns undef:

sub plain { "hi" }
print defined(prototype 'plain') ? "yes" : "no";   # no

A CORE:: query for a built-in whose shape fits the prototype language:

print prototype 'CORE::push';           # \@@
print prototype 'CORE::keys';           # \[%@]
print prototype 'CORE::pos';            # ${\;}

A CORE:: query for a built-in that cannot be expressed as a prototype:

print defined(prototype 'CORE::system') ? "yes" : "no";   # no
print defined(prototype 'CORE::print')  ? "yes" : "no";   # no

Use it to build a wrapper that inherits the callee’s calling convention — useful when writing generic dispatchers:

sub wrap {
    my $name  = shift;
    my $proto = prototype $name;
    # install a new sub with the same prototype string
    eval "sub wrapped_$name ($proto) { goto &$name }";
}

Edge cases#

  • No argument uses $_. prototype with nothing between it and the next term consults $_ as the sub name. A loop like for (@names) { print prototype, "\n" } works by accident of this rule.

  • Signatures are not prototypes. sub f ($x, $y) { ... } declares a signature — prototype 'f' returns undef, because the sub has no prototype. To declare both, use the :prototype(...) attribute: sub f :prototype($$) ($x, $y) { ... }.

  • Unknown name returns undef. If the sub has never been declared, prototype returns undef without raising an error. Combine with defined and exists &Some::Package::name when you need to tell “no prototype” apart from “no such sub”.

  • Auto-loaded subs. If the sub is handled by AUTOLOAD, it has not been compiled yet, so prototype reports undef even when the eventual callable would have one. Force a stub first (*foo = \&foo after loading) if you must query it.

  • References versus names are interchangeable. prototype \&foo and prototype 'foo' return the same string; pick whichever is cheaper at the call site. A reference skips package-name lookup.

  • Fully qualified names. Unqualified names are looked up in the current package. For callers-of-callers, always qualify: prototype 'Other::Pkg::fn'.

  • Empty prototype is not undef. sub nullary () { 42 } gives prototype 'nullary' the empty string "", which is defined and false. Use defined, not truthiness, to test for “has a prototype”.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • sub — declare the subroutine whose prototype you are about to read

  • defined — the correct test for “does this sub have a prototype,” since an empty-string prototype is valid

  • ref — companion inspector when FUNCTION is a code reference and you want to verify the ref type before calling prototype

  • caller — neighbour introspector that answers “who called me,” often used with prototype when building wrappers

  • wantarray — runtime context query, the counterpart to compile-time prototype inspection

  • perlsub — the prototype mini-language and how the parser applies it to call sites