Szukaj…


Uwagi

Podprogramy otrzymują argumenty do zmiennej magicznej o nazwie @_ . Chociaż nie musi być rozpakowywany, jest zalecany, ponieważ poprawia czytelność i zapobiega przypadkowym zmianom, ponieważ argumenty @_ są przekazywane przez odwołanie (można je modyfikować).

Tworzenie podprogramów

Podprogramy są tworzone przy użyciu słowa kluczowego sub po którym następuje identyfikator i blok kodu ujęte w nawiasy klamrowe.

Dostęp do argumentów można uzyskać za pomocą specjalnej zmiennej @_ , która zawiera wszystkie argumenty jako tablicę.

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

Ponieważ funkcja shift domyślnie shift na przesunięcie @_ gdy jest używana wewnątrz podprogramu, powszechnym wzorem jest sekwencyjne wyodrębnianie argumentów do zmiennych lokalnych na początku podprogramu:

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

Alternatywnie, funkcja eksperymentalna "signatures" może być używana do rozpakowywania parametrów, które są przekazywane przez wartość (a nie przez odniesienie).

use feature "signatures";

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

Dla parametrów można użyć wartości domyślnych.

use feature "signatures";

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

Możesz użyć dowolnego wyrażenia, aby nadać parametrowi wartość domyślną - w tym inne parametry.

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

Zauważ, że nie możesz odwoływać się do parametrów, które są zdefiniowane po bieżącym parametrze - dlatego poniższy kod nie działa tak, jak się spodziewano.

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

Argumenty podprogramu są przekazywane przez odwołanie (oprócz tych w podpisach)

Argumenty podprogramów w Perlu są przekazywane przez odwołanie, chyba że znajdują się w podpisie. Oznacza to, że elementy tablicy @_ w sub są tylko aliasami do rzeczywistych argumentów. W poniższym przykładzie $text w programie głównym pozostało zmodyfikowane po wywołaniu podprogramu, ponieważ $_[0] wewnątrz sub jest właściwie inną nazwą dla tej samej zmiennej. Drugie wywołanie powoduje błąd, ponieważ literał łańcuchowy nie jest zmienną i dlatego nie można go modyfikować.

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

Aby uniknąć zapychania zmiennych wywołujących, ważne jest, aby skopiować @_ do zmiennych o @_ lokalnym ( my ... ), jak opisano w „Tworzenie podprogramów”.

Podprogramy

Podprogramy zawierają kod. O ile nie określono inaczej, są one zdefiniowane globalnie.

# 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

Niektóre wbudowane funkcje, takie jak print lub say są słowami kluczowymi, a nie funkcjami, więc np. &say jest niezdefiniowany. Oznacza to również, że możesz je zdefiniować, ale będziesz musiał podać nazwę pakietu, aby je wywołać

# 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

Od Perla 5.18 możesz także mieć funkcje nieglobalne:

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

Od wersji 5.20 możesz także nazywać parametry.

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

Nie należy tego mylić z prototypami, narzędzie, które Perl musi umożliwiać definiowanie funkcji, które zachowują się jak wbudowane. Prototypy funkcji muszą być widoczne w czasie kompilacji, a ich efekty można zignorować, podając & sigil. Prototypy są ogólnie uważane za zaawansowaną funkcję, którą najlepiej stosować z dużą ostrożnością.

# 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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow