Поиск…


замечания

Подпрограммы получают свои аргументы магической переменной @_ . Хотя его не нужно распаковывать, рекомендуется, так как он помогает читать и предотвращает случайные изменения, поскольку аргументы @_ передаются по ссылке (могут быть изменены).

Создание подпрограмм

Подпрограммы создаются с использованием ключевого слова sub за которым следует идентификатор и блок кода, заключенный в фигурные скобки.

Вы можете получить доступ к аргументам, используя специальную переменную @_ , которая содержит все аргументы в виде массива.

sub function_name {
    my ($arg1, $arg2, @more_args) = @_;
    # ...
}

Поскольку по умолчанию shift функции сдвигается @_ при использовании внутри подпрограммы, это обычный шаблон, который последовательно извлекает аргументы в локальные переменные в начале подпрограммы:

sub function_name {
    my $arg1 = shift;
    my $arg2 = shift;
    my @more_args = @_;
    # ...
}

# emulate named parameters (instead of positional)
sub function_name {
    my %args = (arg1 => 'default', @_);
    my $arg1 = delete $args{arg1};
    my $arg2 = delete $args{arg2};
    # ...
}

sub {
    my $arg1 = shift;
    # ...
}->($arg);
5.20.0

Альтернативно, экспериментальная особенность "signatures" может использоваться для распаковки параметров, которые передаются по значению ( не по ссылке).

use feature "signatures";

sub function_name($arg1, $arg2, @more_args) {
    # ...
}

Значения по умолчанию могут использоваться для параметров.

use feature "signatures";

sub function_name($arg1=1, $arg2=2) {
    # ...
}

Вы можете использовать любое выражение, чтобы дать значение по умолчанию для параметра, включая другие параметры.

sub function_name($arg1=1, $arg2=$arg1+1) {
    # ...
}

Обратите внимание, что вы не можете ссылаться на параметры, которые определены после текущего параметра - следовательно, следующий код работает не так, как ожидалось.

sub function_name($arg1=$arg2, $arg2=1) {
    print $arg1;  # => <nothing>
    print $arg2;  # => 1
}

Аргументы подпрограммы передаются по ссылке (кроме записей в подписи)

Аргументы подпрограммы в Perl передаются по ссылке, если они не находятся в подписи. Это означает, что члены массива @_ внутри sub являются просто псевдонимами для фактических аргументов. В следующем примере $text в основной программе остается модифицированным после вызова подпрограммы, потому что $_[0] внутри субфайла фактически является просто другим именем для той же переменной. Второй вызов вызывает ошибку, потому что строковый литерал не является переменной и поэтому не может быть изменен.

use feature 'say';

sub edit {
    $_[0] =~ s/world/sub/;
}

my $text = "Hello, world!";
edit($text);
say $text;      # Hello, sub!

edit("Hello, world!"); # Error: Modification of a read-only value attempted

Поэтому, чтобы @_ переменных вашего вызывающего абонента, важно скопировать @_ на локально измененные переменные ( my ... ), как описано в разделе «Создание подпрограмм».

подпрограммы

Подпрограммы содержат код. Если не указано иное, они определяются глобально.

# 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 &sum; # 1

Некоторые встроенные функции, такие как print или say являются ключевыми словами, а не функциями, поэтому, например, &say undefined. Это также означает, что вы можете определить их, но вам нужно будет указать имя пакета, чтобы на самом деле вызвать их

# 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.
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 &prod; # 1
}
say defined &prod; # 0
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);


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow