require
Richiede una versione di Perl specificata da VERSIONE, o richiede alcune
semantiche specificate da ESPR oppure da $_ se ESPR non viene fornita.
VERSIONE può essere sia un argomento numerico come 5.006, che
viene poi confrontato con $], oppure un valore testuale nella forma di
v5.6.1, che viene poi confrontato con $^V (conosciuto anche come
$PERL_VERSION). Se VERSIONE è più grande della versione
dell'interprete Perl corrente, viene prodotto un errore bloccante al momento
dell'esecuzione. Confrontate require con use, che può compiere
un controllo di questo tipo al momento della compilazione.
In genere, bisognerebbe evitare di specificare VERSIONE come un valore
testuale nella forma v5.6.1, poiché ciò causa, con versioni
vecchie del Perl che non supportano questa sintassi, dei messaggi di errore
fuorvianti. Al suo posto dovrebbe essere usata la versione numerica.
require v5.6.1; # controllo di versione al momento dell'esecuzione
require 5.6.1; # uguale
require 5.006_001; # uguale; preferibile per compatibilitE<agrave> all'indietro
Usata diversamente, require richiede che un file di libreria esterno venga
incluso, se non lo è stato in precedenza. Il file viene incluso con
il meccanismo do-FILE, che essenzialmente è una variante di eval.
Ha semantiche simili alla seguente subroutine:
sub require {
my ($nomefile) = @_;
if (exists $INC{$nomefile}) {
return 1 if $INC{$nomefile};
die "Compilazione fallita nel require";
}
my ($nomefilevero,$risultato);
ITER: {
foreach $prefisso (@INC) {
$nomefilevero = "$prefisso/$nomefile";
if (-f $nomefilevero) {
$INC{$nomefile} = $nomefilevero;
$risultato = do $nomefilevero;
last ITER;
}
}
die "Non trovo $nomefile in \@INC";
}
if ($@) {
$INC{$nomefile} = undef;
die $@;
} elsif (!$risultato) {
delete $INC{$nomefile};
die "$nomefile non ha restituito un valore vero";
} else {
return $risultato;
}
}
Va notato che il file non può venire incluso due volte specificando
lo stesso nome.
Il file deve restituire un valore vero come ultima istruzione, per indicare
il successo dell'esecuzione di qualsiasi codice di inizializzazione, dunque
è consuetudine terminare tale file con 1;, a meno che non si sia
sicuri che restituisca vero in ogni caso. Tuttavia, la cosa migliore è
mettere l'1;, in caso aggiungiate altre istruzioni in un secondo momento.
Se ESPR è una bareword (*), require presume un'estensione ".pm"
e sostituisce per voi "::" con "/" nel nome del file, in modo da
rendere facile il caricamento dei moduli standard. Questo modo di caricare
i moduli non comporta rischi di alterazione dello spazio dei nomi.
In altre parole, se provate questo:
require Pippo::Pluto; # una splendida bareword
La funzione require cercherà in realtà il file
"Pippo/Pluto.pm" nelle directory specificate nell'array @INC.
Ma se provate questa:
$class = 'Pippo::Pluto';
require $class; # $class non e` una bareword
#oppure
require "Pippo::Pluto"; # non e` una bareword per via delle ""
La funzione require cercherà il file "Pippo::Pluto" nell'array
@INC e si lamenterà di non riuscirvi a trovare "Pippo::Pluto".
In questo caso potete scrivere:
eval "require $class";
Ora che avete capito come require cerca i file nel caso di un argomento
bareword, c'è una piccola ulteriore funzionalità che ha luogo
dietro le quinte. Prima che require si metta a cercare una estensione
".pm", cercherà prima un nomefile con una estensione ".pmc".
Un file con questa estensione viene considerato essere del bytecode Perl
generato da B::Bytecode. Se questo file viene trovato e il suo
istante di modifica è più recente di un coincidente e non
compilato file ".pm", verrà caricato al posto del file non compilato
che finisce con una estensione ".pm".
Potete anche inserire degli hook (**) nel servizio di importazione,
inserendo del codice Perl direttamente nell'array @INC. Ci sono tre tipi
di hook: riferimenti a subroutine, riferimenti ad array e oggetti blessed (***).
I riferimenti a subroutine sono il caso più semplice. Quando il
sistema di inclusione esamina @NIC ed incontra una subroutine, essa viene
chiamata con due parametri: il primo è un riferimento a se stessa,
il secondo è il nome del file da includere (es. "Pippo/Pluto.pm").
La soubroutine deve restituire undef oppure un filehandle, dal quale
verrà letto il file da includere. Se viene restituito undef,
require esaminerà i rimanenti elementi di @INC.
Se l'hook è un riferimento ad un array, il primo elemento di tale
array deve essere un riferimento ad una subroutine. Questa subroutine
è chiamata come sopra, ma il primo parametro è il riferimento
all'array. Ciò permette di passare alcuni argomenti alla subroutine,
indirettamente.
In altre parole, potete scrivere:
push @INC, \&mia_sub;
sub my_sub {
my ($refcodice, $nomefile) = @_; # $refcodice e` \&my_sub
...
}
oppure:
push @INC, [ \&mia_sub, $x, $y, ... ];
sub mia_sub {
my ($refarray, $nomefile) = @_;
# Recupera $x, $y, ...
my @parametri = @$refarray[1..$#$refarray];
...
}
Se l'hook è un oggetto, deve fornire un metodo INC che verrà
chiamato come sopra, ed a cui verrà passato l'oggetto stesso come
primo parametro. (Va notato che dovete indicare il nome completo della sub,
poiché esso viene sempre forzato dentro il package main). Di seguito
è riportato un tipico schema di codice:
# In Pippo.pm
package Pluto;
sub new { ... }
sub Pluto::INC {
my ($self, $nomefile) = @_;
...
}
# Nel programma principale
push @INC, new Pluto(...);
Va notato che a questi hook è anche permesso impostare la voce in %INC
corrispondente ai file che essi hanno caricato. Consultate perlvar/%INC.
Per un servizio di importazione ancora più potente, consultate
use e perlmod.
(*) Letteralmente parola nuda, indica una parola che potrebbe essere la
chiamata di una funzione (ma non ha né & all'inizio né ()
alla fine) ed è per questo ambigua per perl a tempo di compilazione.
In assenza di use strict 'subs' (che genera errore) viene trattata come se
fosse inclusa tra virgolette. [NdT]
(**) letterlamente aggancio, questo termine indica la procedura di codificare
un programma che permetta all'utente di espenderlo. Ad esempio il funzionamento
dei plugin di <programma con plugin> è permesso grazie a degli hook. [NdT]
(***) letteralmente santificato, consacrato, si intende di un oggetto che
è stato legato al nome di un package. Si veda la funzione bless. [NdT]