Subroutines hold code. Unless specified otherwise, they are globally defined.
# Functions do not (have to) specify their argument list
sub returns_one {
# Functions return the value of the last expression by default
# The return keyword here is unnecessary, but helps readability.
return 1;
}
# Its arguments are available in @_, however
sub sum {
my $ret = 0;
for my $value (@_) {
$ret += $value
}
return $ret;
}
# Perl makes an effort to make parens around argument list optional
say sum 1..3; # 6
# If you treat functions as variables, the & sigil is mandatory.
say defined ∑ # 1
Some builtins such as print
or say
are keywords, not functions, so e.g. &say
is undefined. It also does mean that you can define them, but you will have to specify the package name to actually call them
# This defines the function under the default package, 'main'
sub say {
# This is instead the say keyword
say "I say, @_";
}
# ...so you can call it like this:
main::say('wow'); # I say, wow.
Since Perl 5.18, you can also have non-global functions:
use feature 'lexical_subs';
my $value;
{
# Nasty code ahead
my sub prod {
my $ret = 1;
$ret *= $_ for @_;
$ret;
}
$value = prod 1..6; # 720
say defined ∏ # 1
}
say defined ∏ # 0
Since 5.20, you can also have named parameters.
use feature 'signatures';
sub greet($name) {
say "Hello, $name";
}
This should not be confused with prototypes, a facility Perl has to let you define functions that behave like built-ins. Function prototypes must be visible at compile time and its effects can be ignored by specifying the &
sigil. Prototypes are generally considered to be an advanced feature that is best used with great care.
# This prototype makes it a compilation error to call this function with anything
# that isn't an array. Additionally, arrays are automatically turned into arrayrefs
sub receives_arrayrefs(\@\@) {
my $x = shift;
my $y = shift;
}
my @a = (1..3);
my @b = (1..4);
receives_arrayrefs(@a, @b); # okay, $x = \@a, $y = \@b, @_ = ();
receives_arrayrefs(\@a, \@b); # compilation error, "Type … must be array …"
BEGIN { receives_arrayrefs(\@a, \@b); }
# Specify the sigil to ignore the prototypes.
&receives_arrayrefs(\@a, \@b); # okay, $x = \@a, $y = \@b, @_ = ();
&receives_arrayrefs(@a, @b); # ok, but $x = 1, $y = 2, @_ = (3,1,2,3,4);