Perl Language
subrutiner
Sök…
Anmärkningar
Subroutiner får sina argument till den magiska variabeln som heter @_
. Även om det inte behöver packas upp rekommenderas det, eftersom det hjälper läsbarheten och förhindrar oavsiktliga förändringar när argument av @_
skickas genom referens (kan ändras).
Skapa subrutiner
Subrutiner skapas genom att använda nyckelordet sub
följt av en identifierare och ett kodblock inneslutna i hängslen.
Du kan komma åt argumenten med hjälp av den specialvariabla @_
, som innehåller alla argument som en matris.
sub function_name {
my ($arg1, $arg2, @more_args) = @_;
# ...
}
Eftersom funktionen shift
standard flytta @_
när den används inuti en subrutin är det ett gemensamt mönster för att extrahera argument i tur och ordning i lokala variabler i början av ett underprogram:
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);
Alternativt kan den experimentella funktionen "signatures"
användas för att packa upp parametrar som passeras efter värde ( inte med referens).
use feature "signatures";
sub function_name($arg1, $arg2, @more_args) {
# ...
}
Standardvärden kan användas för parametrarna.
use feature "signatures";
sub function_name($arg1=1, $arg2=2) {
# ...
}
Du kan använda valfritt uttryck för att ge ett standardvärde till en parameter - inklusive andra parametrar.
sub function_name($arg1=1, $arg2=$arg1+1) {
# ...
}
Observera att du inte kan referera till parametrar som definieras efter den aktuella parametern - följaktligen fungerar följande kod inte helt som förväntat.
sub function_name($arg1=$arg2, $arg2=1) {
print $arg1; # => <nothing>
print $arg2; # => 1
}
Subroutinargument skickas som referens (förutom de i underskrifter)
Subroutinargument i Perl skickas som referens, såvida de inte står i signaturen. Detta innebär att medlemmarna i @_
matrisen inuti @_
bara är alias till de faktiska argumenten. I följande exempel lämnas $text
i huvudprogrammet ändrat efter subroutine-samtalet eftersom $_[0]
inuti suben faktiskt bara är ett annat namn för samma variabel. Den andra kallelsen kastar ett fel eftersom en strängbokstav inte är en variabel och därför inte kan ändras.
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
För att undvika att klaga på din anropsvariabler är det därför viktigt att kopiera @_
till lokalt skopade variabler ( my ...
) enligt beskrivningen under "Skapa subroutiner".
subrutiner
Subroutiner har kod. Om inget annat anges, definieras de globalt.
# 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
Vissa inbyggnader som print
eller say
är nyckelord, inte funktioner, så t.ex. &say
är odefinierat. Det betyder också att du kan definiera dem, men du måste ange paketnamnet för att faktiskt ringa dem
# 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.
Sedan Perl 5.18 kan du också ha icke-globala funktioner:
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
Sedan 5.20 kan du också ha namngivna parametrar.
use feature 'signatures';
sub greet($name) {
say "Hello, $name";
}
Detta bör inte förväxlas med prototyper, en anläggning som Perl måste låta dig definiera funktioner som uppför sig som inbyggda. Funktionsprototyper måste vara synliga vid sammanställningstiden och dess effekter kan ignoreras genom att ange &
sigil. Prototyper anses generellt vara en avancerad funktion som bäst används med stor omsorg.
# 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);