![]() |
| index | project | pods | responsabili |
NOMEperlmod - moduli Perl (pacchetti e tabelle dei simboli)
DESCRIZIONE
PacchettiPerl mette a disposizione un meccanismo in cui spazi dei nomi alternativi
fanno in modo che le variabili dei pacchetti non facciano a botte con le
altre. Infatti, non
esiste qualcosa di esattamente corrispondente ad una variabile globale
in Perl. L'istruzione Il vecchio delimitatore per i pacchetti era un apice singolo, ma la
coppia di due punti è ora il delimitatore preferito, in parte perché
più leggibile per gli umani, in parte perché è più leggibile dalle
macro di emacs. In più fa sentire i programmatori C++ come se sapessero
cosa sta succedendo -- contrariamente a quando si utilizza l'apice singolo
come separatore, che stava lì per far sentire i programmatori Ada come
se sapessero cosa stava succedendo. Poiché la sintassi vecchia
maniera è ancora supportata per compatibilità, se provate ad utilizzare
una stringa come I pacchetti possono, a loro volta, contenere separatori di pacchetto,
come in Solo gli identificatori che cominciano con lettere (o underscore
[il trattino basso ``_'', N.d.T.] sono registrate nella tabella dei
simboli di un pacchetto. Tutti gli altri simboli sono tenuti nel
pacchetto Le variabili che cominciano con underscore una volta erano forzate
all'interno del pacchetto Le stringhe passate ad Il simbolo speciale Consultate perlsub per altre questioni sul campo d'azione relative a
Tabelle dei SimboliLa tabella dei simboli per un pacchetto viene memorizzata nell'hash con
il nome del pacchetto ed una coppia di punto e virgola giustapposti. La tabella
dei simboli principale risulta pertanto essere IL valore in ciascun elemento dell'hash è ciò a cui vi riferite quando
utilizzate la notazione typeglob
local *main::pippo = *main::pluto;
local $main::{pippo} = $main::{pluto};
(Siate sicuri di notare la enorme differenza fra la seconda riga
qui sopra e Potete utilizzare quanto detto per stampare tutte le variabili in un pacchetto, ad esempio. La libreria standard, ma datata, dumpvar.pl ed il modulo CPAN Devel::Symdump si basano proprio su questa caratteristica. L'assegnazione ad un typeglob effettua un'operazione di identificazione, ossia:
*pippo = *pluto
fa sì che variabili, subroutine, formati e handle di file e directory
accessibili attraverso l'identificatore
*pippo = \$pluto;
Ciò rende C'è una sottile differenza fra le seguenti istruzioni:
*pippo = *pluto;
*pippo = \$pluto;
$pluto = 1;
*pippo = \$pluto; # Rende $pippo un alias di $pluto
{
local $pluto = 2; # Modifica ristretta al blocco
print $pippo; # Stampa '1'!
}
stamperebbe '1', perché Quel che rende tutto ciò importante è il fatto che il modulo Exporter utilizza gli alias glob come meccanismo di importazione/esportazione. La possibilità di localizzare in maniera appropriata una variabile che è stata esportata da un modulo dipende dal modo in cui è stata esportata:
@EXPORT = qw( $pippo ); # Forma abituale, non puo` essere localizzata
@EXPORT = qw( *pippo ); # Questa si puo` localizzare
Potete aggirare il primo caso utilizzando il nome pienamente qualificato
( Il meccanismo
%una_hash = (); # non puo` essere my()
*una_hash = fn( \%altra_hash );
sub fn {
local *hashsym = shift;
# ora utilizzate %hashsym normalmente, ed andrete
# a modificare %altra_hash chiamata
my %nhash = (); # fate cio` che volete
return \%nhash;
}
All'uscita dalla funzione, il riferimento sovrascriverà l'elemento
per la hash nella tabella dei simboli specificato dal typeglob
Un altro utilizzo delle tabelle dei simboli lo si ha per realizzare scalari ``costanti''.
*PI = \3.14159265358979;
Ora non potete modificare Potete dire
sub identifica_typeglob {
my $glob = shift;
print 'Mi hai passato ', *{$glob}{PACKAGE}, '::', *{$glob}{NAME}, "\n";
}
identifica_typeglob *pippo;
identifica_typeglob *pluto::topolino;
Questo stampa
Mi hai passato main::pippo
Mi hai passato pluto::topolino
La notazione Le definizioni delle subroutine (e le dichiarazione, per quel che importa) non devono essere necessariamente poste nel pacchetto della tabella dei simboli che vanno ad occupare. Potete definire una subroutine al di fuori del suo pacchetto qualificando esplicitamente il nome della subroutine:
package main;
sub Un_Pacchetto::pippo { ... } # &pippo definita in Un_Pacchetto
Questa risulta solo una scorciatoia per un'assegnazione di typeglob in fase di compilazione:
BEGIN { *Un_Pacchetto::pippo = sub { ... } }
e non è la stessa cosa di:
{
package Un_Pacchetto;
sub pippo { ... }
}
Nelle prime due versioni il corpo della subroutine risiede lessicalmente
nel pacchetto
package main;
$Un_Pacchetto::nome = "achille";
$main::nome = "ulisse";
sub Un_Pacchetto::pippo {
print "sono in ", __PACKAGE__, ": \$nome e` '$nome'\n";
}
Un_Pacchetto::pippo();
stampa:
sono in main: $nome e` 'ulisse'
invece che:
sono in Un_Pacchetto: $nome e` 'achille'
Questa differenza ha anche implicazioni nell'uso del qualificatore SUPER:: (consultate perlobj).
BEGIN, CHECK, INIT e ENDQuattro blocchi di codice chiamati in maniera speciale vengono eseguiti
all'inizio ed alla fine di un programma Perl in esecuzione: Questi blocchi possono essere preceduti da Un blocco Va notato che i blocchi di codice Un blocco Osservate che i blocchi di codice All'interno di un blocco I blocchi I blocchi I blocchi Quando utilizzate le opzioni -n e -p di Perl, Il seguente programma controlla_begin rende infine tutto chiaro: #!/usr/bin/perl # controlla_begin print " 8. Codice ordinario a runtime.\n";
END { print "14. Questa e` dunque la fine della favola.\n" }
INIT { print " 5. I blocchi INIT sono eseguiti in FIFO appena prima del runtime.\n" }
CHECK { print " 4. Questa e` dunque la quarta riga.\n" }
print " 9. Viene eseguita in ordine, chiaramente.\n";
BEGIN { print " 1. I blocchi BEGIN sono eseguiti in FIFO durante la compilazione.\n" }
END { print "13. Consultate perlmod per il resto della storia.\n" }
CHECK { print " 3. I blocchi CHECK sono eseguiti in LIFO alla fine della compilazione.\n" }
INIT { print " 6. Provate a rieseguire questo programma con l'opzione -c.\n" }
print "10. Questo e` codice anti-offuscato.\n";
END { print "12. I blocchi END sono eseguiti in LIFO al momento di uscire.\n" }
BEGIN { print " 2. Questa viene dunque fuori come seconda.\n" }
INIT { print " 7. Vedrete la differenza in quattro e quattr'otto.\n" }
print "11. E` solo che _sembra_ essere confuso.\n"; __END__
Classi PerlNon esiste alcuna sintassi speciale per le classi in Perl, ma un pacchetto
può comportarsi come una classe se mette a disposizione subroutine che
si comportano come metodi. Un tale pacchetto può anche derivare qualcuno
dei suoi metodi da un'altra classe (pacchetto) inserendo i nomi degli
altri pacchetti nel suo array globale Per maggiori dettagli consultate perltoot e perlobj.
Moduli PerlUn modulo è solamente un insieme di funzioni correlate in un file di libreria, ossia un pacchetto Perl con lo stesso nome del file. Viene progettato specificamente per essere riutilizzabile da parte di altri moduli o programmi. Può ottenere questo scopo fornendo un meccanismo per esportare alcuni dei propri simboli nella tabella dei simboli di qualunque pacchetto che lo utilizza, o potrebbe lavorare come una definizione di classe e far sì che la propria semantica sia disponibile implicitamente attraverso chiamate ai metodi sulla classe e sui suoi oggetti, senza esportare niente esplicitamente. O potrebbe fare un po' di tutti e due. Ad esempio, per iniziare un modulo tradizionale e non orientato agli oggetti chiamato Qualche::Modulo, create un file chiamato Qualche/Modulo.pm e cominciate con questo modello:
package Qualche::Modulo; # si assume Qualche/Modulo.pm
use strict;
use warnings;
BEGIN {
use Exporter ();
our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
# imposta la versione per il controllo della stessa
$VERSION = 1.00;
# se si sta utilizzando RCS/CVS, questa potrebbe essere migliore
$VERSION = sprintf "%d.%03d", q$Revision: 1.6 $ =~ /(\d+)/g;
@ISA = qw(Exporter);
@EXPORT = qw(&funz1 &funz2 &funz4);
%EXPORT_TAGS = ( ); # esempio: TAG => [ qw!nome1 nome2! ],
# Le vostre variabili globali di pacchetto vanno qui
# cosi` come qualsiasi funzione esportata opzionalmente
@EXPORT_OK = qw($Var1 %Hashit &funz3);
}
our @EXPORT_OK;
# variabili globali di pacchetto esportate vanno qui
our $Var1;
our %Hashit;
# variabili globali di pacchetto non esportate vanno qui
our @more;
our $stuff;
# inizializza le variabili globali di pacchetto, prima quelle esportate
$Var1 = '';
%Hashit = ();
# poi le altre (che sono ancora accessibili attraverso
# $Qualche::Modulo::roba)
$roba = '';
@altro = ();
# Tutte le variabili lessicali limitate al file devono essere
# create prima delle funzioni piE<ugrave> in basso che le utilizzano
# Variabili lessicali private per il file vanno qui
my $priv_var = '';
my %hash_segreto = ();
# Ecco una funzione privata del file implementata come chiusura,
# chiamabile come &$priv_func; non puE<ograve> essere associata ad un prototipo.
my $priv_func = sub {
# la roba va qui.
};
# Create le vostre funzioni qui, sia quelle esportate che quelle
# non esportate. Ricordatevi di inserire qualcosa di interessante
# nelle parentesi graffe!
sub funz1 {} # nessun prototipo
sub funz2() {} # prototipo void [vuoto, N.d.T.]
sub funz3($$) {} # prototipo con due scalari
# Questa non viene esportata, ma potrebbe essere chiamata!
sub funz4(\%) {} # prototipo con un riferimento ad hash
END { } # pulizia del modulo (distruttore globale)
## IL VOSTRO CODICE VA QUI
1; # non dimenticate di restituire un valore vero dal file
Successivamente andate avanti a dichiarare ed utilizzare le vostre variabili in funzioni senza nessun tipo di qualifica. Consultate Exporter e perlmodlib per maggiori dettagli sulla meccanica e su problematiche di stile relative alla creazione di moduli. I moduli Perl sono inclusi nel vostro programma dicendo
use Modulo;
oppure
use Modulo LISTA;
Ciò equivale esattamente a
BEGIN { require Modulo; import Modulo; }
ovvero
BEGIN { require Modulo; import Modulo LISTA; }
Come caso particolare
use Module ();
è esattamente equivalente a
BEGIN { require Modulo; }
Tutti i file di modulo Perl condividono l'estensione .pm. L'operatore
Le due istruzioni:
require QualcheModulo;
require "QualcheModulo.pm";
differiscono fra loro in due sensi. Nel primo caso, qualunque
doppio punto e virgola nel nome del modulo, come in Poiché l'istruzione
require Cwd; # rende Cwd:: accessibile
$qui = Cwd::getcwd();
use Cwd; # importa i nomi da Cwd::
$qui = getcwd();
require Cwd; # rende Cwd:: accessibile
$qui = getcwd(); # oops! nessuna subroutine main::getcwd()
In generale, I pacchetti Perl possono essere innestati all'interno di altri nomi di
pacchetti, cosicché possiamo avere nomi di pacchetti contenenti I moduli Perl hanno sempre un file .pm, ma possono anche esserci
eseguibili collegati dinamicamente (spesso questi terminano con
.so) o definizioni di subroutine caricate automaticamente (che
spesso terminano in .al) associate al modulo. Se questo è il caso,
queste saranno comunque completamente trasparenti all'utente del
modulo. È responsabilità del file .pm di caricare (o metter
su un autoload) qualsiasi funzionalità aggiuntiva. Ad esempio,
sebbene il modulo POSIX faccia sia caricamento dinamico che
autocaricamento, l'utente può dire semplicemente
Rendere il vostro modulo sicuro per il multithreadingA partire dalla versione 5.6.0 Perl ha supportato un nuovo tipo di thread chiamato thread di interprete (ithreads). Questi thread possono essere utilizzati esplicitamente o implicitamente. Gli Ithreads lavorano clonando l'albero dei dati cosicché non esistono
dati condivisi fra thread differenti. Questi thread possono essere
utilizzati mediante il modulo Se volete utilizzare A partire dalla versione 5.8.7, Perl supporta anche la subroutine speciale
Come
VEDETE ANCHEConsultate perlmodlib per questioni generali di stile relative alla realizzazione di moduli e classi Perl, così come per trovare descrizioni della libreria standard e CPAN; Exporter per sapere come lavora il meccanismo standard di Perl per importare/esportare i simboli; perltoot e perltooc per un tutorial approfondito sulla creazione di classi; perlobj per trovare un documento di riferimento spinto sugli oggetti; perlsub per una spiegazione delle funzioni e del campo d'azione. Infine, consultate perlxstut e perlguts per maggiori informazioni su come scrivere moduli di estensione.
TRADUZIONE
VersioneLa versione su cui si basa questa traduzione è ottenibile con: perl -MPOD2::IT -e print_pod perlmod Per maggiori informazioni sul progetto di traduzione in italiano si veda http://pod2it.sourceforge.net/ .
TraduttoreTraduzione a cura di Flavio Poletti.
RevisoreRevisione a cura di dree. Mon Jun 11 22:02:17 2012 |