Perl Language
Le subroutine
Ricerca…
Osservazioni
Le subroutine ottengono i loro argomenti alla variabile magica chiamata @_
. Anche se non deve essere decompresso, è consigliato, in quanto aiuta la leggibilità e previene le modifiche accidentali poiché gli argomenti di @_
vengono passati per riferimento (possono essere modificati).
Creazione di subroutine
Le subroutine vengono create usando la parola chiave sub
seguita da un identificatore e un blocco di codice racchiuso tra parentesi graffe.
È possibile accedere agli argomenti utilizzando la variabile speciale @_
, che contiene tutti gli argomenti come una matrice.
sub function_name {
my ($arg1, $arg2, @more_args) = @_;
# ...
}
Poiché la funzione shift
@_
valore predefinito lo shifting @_
quando viene usata all'interno di una subroutine, è un modello comune per estrarre gli argomenti in modo sequenziale in variabili locali all'inizio di una 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);
In alternativa, è possibile utilizzare la funzionalità sperimentale "signatures"
per decomprimere i parametri, che vengono passati per valore ( non per riferimento).
use feature "signatures";
sub function_name($arg1, $arg2, @more_args) {
# ...
}
I valori predefiniti possono essere utilizzati per i parametri.
use feature "signatures";
sub function_name($arg1=1, $arg2=2) {
# ...
}
È possibile utilizzare qualsiasi espressione per fornire un valore predefinito a un parametro, inclusi altri parametri.
sub function_name($arg1=1, $arg2=$arg1+1) {
# ...
}
Si noti che non è possibile fare riferimento ai parametri definiti dopo il parametro corrente, quindi il codice seguente non funziona come previsto.
sub function_name($arg1=$arg2, $arg2=1) {
print $arg1; # => <nothing>
print $arg2; # => 1
}
Gli argomenti di subroutine vengono passati per riferimento (eccetto quelli nelle firme)
Gli argomenti di subroutine in Perl vengono passati per riferimento, a meno che non siano nella firma. Ciò significa che i membri dell'array @_
all'interno del sub sono solo alias degli argomenti effettivi. Nell'esempio seguente, $text
nel programma principale viene modificato dopo la chiamata alla subroutine perché $_[0]
all'interno del sub è in realtà solo un nome diverso per la stessa variabile. La seconda invocazione genera un errore perché una stringa letterale non è una variabile e quindi non può essere modificata.
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
Per evitare di clobare le variabili del chiamante è quindi importante copiare @_
in variabili con scope locale ( my ...
) come descritto in "Creazione di subroutine".
Le subroutine
Le subroutine contengono il codice. Se non diversamente specificato, sono definiti a livello globale.
# 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
Alcuni builtin come ad esempio print
o say
sono parole chiave, non funzioni, quindi ad esempio &say
non è definito. Significa anche che è possibile definirli, ma è necessario specificare il nome del pacchetto per chiamarli effettivamente
# 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.
Dal Perl 5.18, puoi anche avere funzioni non globali:
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
Dalla 5.20, puoi anche avere parametri con nome.
use feature 'signatures';
sub greet($name) {
say "Hello, $name";
}
Questo non dovrebbe essere confuso con i prototipi, una struttura che Perl deve permettervi di definire funzioni che si comportano come built-in. I prototipi di funzioni devono essere visibili al momento della compilazione e i suoi effetti possono essere ignorati specificando il &
sigil. I prototipi sono generalmente considerati una funzionalità avanzata che viene utilizzata al meglio con grande cura.
# 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);