子程序

子程序保存代码。除非另有说明,否则它们是全局定义的。

# 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

一些内置printsay 是关键字,而不是函数,所以例如 &say 是未定义的。它也意味着你可以定义它们,但你必须指定包名称才能实际调用它们

# 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.

Version >= 5.18.0

从 Perl 5.18 开始,你还可以拥有非全局函数:

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

Version >= 5.20.0

从 5.20 开始,你还可以使用命名参数。

use feature 'signatures';
sub greet($name) {
  say "Hello, $name";
}

应该与原型相混淆,Perl 必须让你定义与内置函数类似的函数。函数原型必须在编译时可见,并且可以通过指定 & sigil 来忽略其效果。原型通常被认为是一种高级功能,最好小心使用。

# 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);