Fatta eccezione per le espressioni regolari, dovete passare un riferimento a
questi oggetti. Consultate perlsub/"Pass by Reference" ["Passato per Riferimento", NdT]
per tale particolare questione, e perlref per informazioni sui riferimenti.
Consultate il sottostante paragrafo "Passaggio di espressioni regolari",
per avere informazioni sul passaggio di espressioni regolari.
- Passaggio di variabili e funzioni
Le variabili e le funzioni sono abbastanza facili da passare: limitatevi
a passare un riferimento ad una variabile esistente o anonima, oppure
ad una funzione:
funz( \$un_certo_scalare );
funz( \@un_certo_array );
funz( [ 1 .. 10 ] );
funz( \%un_certo_hash );
funz( { questo => 10, quello => 20 } );
funz( \&una_certa_funzione );
funz( sub { $_[0] ** $_[1] } );
- Passaggio di filehandle
Dal perl 5.6, potete rappresentare i filehandle con variabili scalari
che trattare come ogni altro scalare.
open my $fh, $nomefile or die "Non posso aprire $nomefile! $!";
funz( $fh );
sub funz {
my $fh_passato = shift;
my $linea = <$fh>;
}
Prima del Perl 5.6, dovevate usare le notazioni *FH oppure \*FH .
Queste sono "typeglob"--per maggiori informazioni, consultate
perldata/"Typeglobs and Filehandles" ["Typglob e Filehandle", NdT] e in modo
particolare perlsub/"Pass by Reference" ["Passato per Riferimento", NdT].
- Passaggio di espressioni regolari
Per passare espressioni regolari, è necessario usare una versione di
Perl sufficientemente recente da supportare il costrutto qr//, passare
stringhe e usare eval in maniera tale che catturi le eccezioni o altrimenti
essere molto, molto furbi.
Ecco un esempio che mostra come si fa a passare una stringa che deve
essere verificata con una espressione regolare, usando qr//:
sub verifica($$) {
my ($val1, $regex) = @_;
my $retval = $val1 =~ /$regex/;
return $retval;
}
$corrispondenza = verifica("old McDonald", qr/d.*D/i);
Va notato che qr// permette di usare i flag alla fine. Quel pattern viene
compilato a tempo di compilazione, benché venga eseguito
successivamente.
La notazione qr// non è stata introdotta che con la versione 5.005.
In precedenza ci si doveva avvicinare al problema in maniera molto meno
intuitiva. Ecco lo stesso esempio, nel caso non si abbia qr//:
sub verifica($$) {
my ($val1, $regex) = @_;
my $retval = eval { $val1 =~ /$regex/ };
die if $@;
return $retval;
}
$corrispondenza = verifica("old McDonald", q/($?i)d.*D/);
Assicuratevi di non scrivere mai cose del genere:
return eval "\$val =~ /$regex/"; # SBAGLIATO
altrimenti qualcuno potrebbe insinuare comandi di shell a causa della
doppia interpolazione dell'eval e della stringa tra doppi apici.
Ad esempio:
$pattern_malefico = 'pericolo ${ system("rm -rf * &") } pericolo';
eval "\$stringa =~ /$pattern_malefico/";
Chi preferisce essere molto molto furbo può consultare il volume della
O'Reilly "Mastering Regular Expressions", di Jeffrey Friedl.
La Build_MathMany_Function(), che si trova a pagina 273, è particolarmente
interessante. Gli estremi completi di questo testo si trovano in perlfaq2.
- Passaggio di metodi
Per passare un metodo ad una subroutine, potete fare così:
chiamata_multipla(10, $un_certo_oggetto, "nome_metodo")
sub chiamata_multipla {
my ($contatore, $oggetto, $metodo) = @_;
for (my $i = 0; $i < $contatore; $i++) {
$oggetto->$metodo();
}
}
Oppure potete usare una chiusura per impacchettare l'oggetto, la
chiamata al metodo e gli argomenti:
my $non_manca_niente = sub { $un_certo_oggetto->obfuscate(@args) };
funz($non_manca_niente);
sub funz {
my $codice = shift;
&$codice();
}
Potete inoltre indagare sul metodo can() della classe UNIVERSAL (inclusa
nella distribuzione standard di perl).