Perl Language
subroutines
Zoeken…
Opmerkingen
Subroutines krijgen hun argumenten voor de magische variabele @_
. Hoewel het niet hoeft te worden uitgepakt, wordt het aanbevolen, omdat het de leesbaarheid helpt en onbedoelde wijzigingen voorkomt omdat argumenten van @_
worden doorgegeven door middel van verwijzing (kunnen worden gewijzigd).
Subroutines maken
Subroutines worden gemaakt met behulp van het trefwoord sub
gevolgd door een ID en een codeblok tussen accolades.
U kunt toegang krijgen tot de argumenten met behulp van de speciale variabele @_
, die alle argumenten als een array bevat.
sub function_name {
my ($arg1, $arg2, @more_args) = @_;
# ...
}
Omdat de functie shift
standaard verschuift @_
wanneer gebruikt in een subroutine, is het een gebruikelijk patroon om de argumenten opeenvolgend te extraheren in lokale variabelen aan het begin van een subroutine:
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);
Als alternatief kan het experimentele kenmerk "signatures"
worden gebruikt om parameters uit te pakken, die worden doorgegeven door waarde ( niet door verwijzing).
use feature "signatures";
sub function_name($arg1, $arg2, @more_args) {
# ...
}
Standaardwaarden kunnen worden gebruikt voor de parameters.
use feature "signatures";
sub function_name($arg1=1, $arg2=2) {
# ...
}
U kunt elke uitdrukking gebruiken om een parameter een standaardwaarde te geven - inclusief andere parameters.
sub function_name($arg1=1, $arg2=$arg1+1) {
# ...
}
Merk op dat u niet kunt verwijzen naar parameters die na de huidige parameter zijn gedefinieerd - daarom werkt de volgende code niet helemaal zoals verwacht.
sub function_name($arg1=$arg2, $arg2=1) {
print $arg1; # => <nothing>
print $arg2; # => 1
}
Subroutine-argumenten worden doorgegeven door middel van verwijzing (behalve die in handtekeningen)
Subroutine-argumenten in Perl worden doorgegeven als referentie, tenzij ze in de handtekening staan. Dit betekent dat de leden van de array @_
in de sub slechts aliassen zijn voor de eigenlijke argumenten. In het volgende voorbeeld wordt $text
in het hoofdprogramma gewijzigd na de aanroep van de subroutine omdat $_[0]
in de sub eigenlijk gewoon een andere naam is voor dezelfde variabele. De tweede aanroep veroorzaakt een fout omdat een letterlijke tekenreeks geen variabele is en daarom niet kan worden gewijzigd.
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
Om te voorkomen dat de variabelen van uw beller in de war raken, is het daarom belangrijk om @_
te kopiëren naar lokaal bereikbare variabelen ( my ...
) zoals beschreven onder "Subroutines maken".
subroutines
Subroutines bevatten code. Tenzij anders aangegeven, zijn ze globaal gedefinieerd.
# 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
Sommige ingebouwde functies zoals print
of say
zijn sleutelwoorden, geen functies, dus bijvoorbeeld &say
is niet gedefinieerd. Het betekent ook dat u ze kunt definiëren, maar u moet de pakketnaam opgeven om ze daadwerkelijk op te roepen
# 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.
Sinds Perl 5.18 kunt u ook niet-globale functies hebben:
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
Sinds 5.20 kunt u ook benoemde parameters hebben.
use feature 'signatures';
sub greet($name) {
say "Hello, $name";
}
Dit moet niet worden verward met prototypes, een faciliteit die Perl u moet laten definiëren voor functies die zich als ingebouwd gedragen. Functieprototypes moeten zichtbaar zijn tijdens het compileren en de effecten ervan kunnen worden genegeerd door de &
sigil op te geven. Prototypes worden over het algemeen beschouwd als een geavanceerde functie die het beste met grote zorg kan worden gebruikt.
# 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);