![]() |
index | project | pods | responsabili |
NOMEIl brevissimo tutorial di Mark a proposito dei riferimenti
DescrizioneUna delle più importanti nuove caratteristiche di Perl 5 era la capacità di gestire strutture dati complesse come gli array o le hash annidate. Per consentirlo, Perl 5 ha introdotto una nuova feature chiamata 'riferimento', e l'uso dei riferimenti è la chiave per gestire, con Perl, dati complessi e strutturati. Sfortunatamente, c'è un sacco di sintassi bizzarra da imparare, e la pagina principale del manuale può risultare difficile da seguire. Il manuale è piuttosto completo, e a volte la gente trova che questo sia un problema, poiché può essere difficile comunicare cosa è importante e cosa non lo è. Fortunatamente, avete bisogno solo di un 10% di quanto viene detto nella pagina principale, per avere il 90% del beneficio. Questa pagina vi mostrerà quel 10%.
Chi ha bisogno di strutture dati complesse?Un problema che saltava fuori spesso con Perl 4 era come rappresentare una hash i cui valori fossero liste. Perl 4 aveva le hash, naturalmente, ma i valori dovevano essere scalari, non potevano essere liste. Perché si dovrebbe volere una hash di liste? Prendiamo un semplice esempio: avete un file contenente nomi di città e nomi di paesi, come questo: Chicago, USA Francoforte, Germania Berlino, Germania Washington, USA Helsinki, Finlandia New York, USA E volete produrre un output come queste, con ogni paese menzionato una sola volta, e poi una lista delle città presenti in quel paese, in ordine alfabetico: Finlandia: Helsinki. Germania: Berlino, Francoforte. USA: Chicago, New York, Washington. La maniera naturale per fare ciò è avere una hash le cui chiavi siano
i nomi dei paesi. Associata ad ogni nome di paese c'è una lista con le
città presenti in quel paese. Ogni volta che si legge una linea dell'input,
la si spezza ( Se i valori della hash non possono essere liste, avete perso. In Perl 4, i valori delle hash non possono essere liste; possono soltanto essere stringhe. Avete perso. Dovreste probabilmente combinare in qualche modo tutti i nomi di città in una singola stringa, e poi, quando viene il momento di scrivere l'output, dovreste spezzare la stringa in una lista, ordinare la lista e ritrasformarla in una stringa. È un lavoraccio, e soggetto ad errori. Ed è frustrante, poiché il Perl ha già le liste, del tutto adatte, che potrebbero risolvere il problema se soltanto poteste usarle.
La soluzioneNel tempo in cui Perl 5 nasceva, eravamo già impantanati in questo design: i valori delle hash devono essere scalari. La soluzione sono i riferimenti. Un riferimento è un valore scalare che si riferisce ad un intero array oppure ad un'intera hash (o a qualunque altra cosa). I nomi sono tipi di riferimento con cui probabilmente avete già familiarità. Pensate al Presidente degli Stati Uniti: una complicata e scomoda massa di carne e ossa. Ma per parlare di lui, o per rappresentarlo in un programma, tutto ciò di cui c'è bisogno è la facile e comoda stringa ``George Bush''. I riferimenti in Perl sono come i nomi per gli array e le hash. Sono i nomi interni, privati, del Perl, quindi potete stare sicuri che non sono ambigui. A differenza di ``George Bush'', una reference fa riferimento ad una cosa sola, e sapete sempre a cosa si riferisce. Se avete un riferimento ad un array, da esso potete ottenere l'intero array. Se avete un riferimento ad una hash, potete ottenere l'intera hash. Ma il riferimento rimane un semplice scalare. Non potete avere una hash i cui valori siano array; i valori in una hash possono solo essere scalari. Da qui non ci smuoviamo. Però un singolo riferimento può referenziare un intero array, e i riferimenti sono scalari, quindi potete avere una hash di riferimenti ad array, e sarà utile quanto una hash di array. Torneremo al problema paesi-città più tardi, dopo che avremo visto un po' di sintassi per gestire i riferimenti.
SintassiCi sono solo due modi per costruire un riferimento, e solo due modi per usarne uno una volta che lo avete.
Costruire riferimenti
Primo modoSe mettete un $arif = \@array; # $arif ora contiene un riferimento ad @array $hrif = \%hash; # $hrif ora contiene un riferimento ad %hash Una volta che il riferimento è memorizzato in una variabile come $aref o $href, potete copiarlo o memorizzarlo così come qualunque altro scalare. $xy = $aref; # $xy contiene una reference ad @array $p[3] = $href; # $p[3] contiene una reference ad %hash $z = $p[3]; # $z cotiene una reference ad %hash Questi esempi mostrano come costruire riferimenti a variabili usandone i nomi. A volte può capitare che vogliate fare un array o una hash senza nome. È un caso analogo all'usare la stringa ``\n'' o il numero 80 senza che esso sia memorizzato prima in una variabile.
Secondo modo
$aref = [1, "pippo", undef, 13]; # $aref contiene un riferimento all'array $href = { APR => 4, AUG => 8 }; # $href contiene un riferimento alla hash I riferimenti ottenuti nel secondo modo sono dello stesso tipo di quelli ottenuti nel primo modo: # Questo... $aref = [1, 2, 3]; # ... ha lo stesso effetto di questo @array = (1, 2, 3); $aref = \@array; La prima linea è un'abbreviazione delle altre due, eccetto per il fatto che
non crea la variabile Se scrivete semplicemente
Usare i riferimentiChe cosa si può fare con un riferimento una volta che ne avete uno? È un valore scalare, e abbiamo visto che potete memorizzarlo come uno scalare, e ripescarlo esattamente come uno scalare. Ma ci sono un altro paio di modi per usarlo:
Primo metodoSe Ecco alcuni esempi: Array: @a @{$aref} Un array reverse @a reverse @{$aref} Inverte l'array $a[3] ${$aref}[3] Un elemento dell'array $a[3] = 17; ${$aref}[3] = 17 Assegnare un elemento In ogni linea ci sono due espressioni che fanno la stessa cosa. La versione a
sinistra opera sull'array L'uso di un riferimento ad hash è esattamente la stessa cosa: %h %{$href} Una hash keys %h keys %{$href} Prende le chiavi dalla hash $h{'red'} ${$href}{'red'} Un elemento della hash $h{'red'} = 17 ${$href}{'red'} = 17 Assegna un elemento Qualsiasi cosa vogliate fare con un riferimento, il Primo metodo vi dice
come farlo. È sufficiente che scriviate il codice Perl che avreste scritto
per fare la stessa identica cosa con un normale array o hash, e poi
sostituire for my $elemento (@array) { ... } quindi rimpiazzate il nome dell'array, for my $elemento (@{$riferimento_ad_array}) { ... } ``Come faccio a stampare il contenuto di una hash quando tutto ciò che ho è un riferimento?'' Prima scrivete il codice per stampare una hash generica: for my $chiave (keys %hash) { print "$chiave => $hash{$chiave}\n"; } e successivamente rimpiazzate il nome della hash con il riferimento fra parentesi graffe: for my $chiave (keys %{$riferimento_ad_hash}) { print "$chiave => ${$riferimento_ad_hash}{$chiave}\n"; }
Secondo metodoIl Primo metodo di utilizzo è tutto ciò di cui avete veramente bisogno, perché vi dice come fare qualunque cosa di cui possiate mai avere bisogno. Ma l'operazione più comune su un array o su una hash è l'estrazione di un singolo elemento, e la sintassi del Primo metodo è involuta. Per questo motivo esistono delle abbreviazioni.
Se Analogamente,
Un esempioVediamo un esempio di come questo sia utile. Per prima cosa, ricordate che Ora pensate a @a = ( [1, 2, 3], [4, 5, 6], [7, 8, 9] );
La notazione pare ancora poco maneggevole, quindi c'è ancora un'altra abbreviazione.
La regola della frecciaTra due indici, la freccia è opzionale. Al posto di Ora sembrano davvero array bidimensionali! Potete rendervi conto del perché le freccie sono importanti. Senza di esse,
dovremmo scrivere
La soluzioneEd ecco la risposta al problema che avevo posto prima, riformattare un file contenente nomi di città e paesi. 1 my %tabella; 2 while (<>) { 3 chomp; 4 my ($citta, $nazione) = split /, /; 5 $tabella{$nazione} = [] unless exists $tabella{$nazione}; 6 push @{$tabella{$nazione}}, $citta; 7 } 8 foreach $nazione (sort keys %tabella) { 9 print "$nazione: "; 10 my @le_citta = @{$tabella{$nazione}}; 11 print join ', ', sort @le_citta; 12 print ".\n"; 13 } Il programma è costituito da due parti. Le linee 2--7 leggono l'input e
costruiscono la struttura dati, e le linee 8--13 analizzano i dati e stampano
il rapporto. Otterremo una hash, %tabella +-----------+---+ | | | +-------------+---------+ | Germania | *---->| Francoforte | Berlino | | | | +-------------+---------+ +-----------+---+ | | | +----------+ | Finlandia | *---->| Helsinki | | | | +----------+ +-----------+---+ | | | +---------+------------+----------+ | USA | *---->| Chicago | Washington | New York | | | | +---------+------------+----------+ +-----------+---+ Per cominciare, ci concentreremo sull'uscita. Supponendo di avere già questa struttura dati, come la stampiamo? 8 foreach $nazione (sort keys %tabella) { 9 print "$nazione: "; 10 my @le_citta = @{$tabella{$nazione}}; 11 print join ', ', sort @le_citta; 12 print ".\n"; 13 }
@le_citta = @array; eccetto che il nome Le righe 2--7 hanno la responsabilità di costruire la struttura dati di partenza. Ecco di nuovo i riferimenti: 2 while (<>) { 3 chomp; 4 my ($citta, $nazione) = split /, /; 5 $tabella{$nazione} = [] unless exists $tabella{$nazione}; 6 push @{$tabella{$nazione}}, $citta; 7 } Le righe 2--4 acquisiscono il nome di una città e della nazione in cui si trova.
La riga 5 verifica se il nome della nazione è già presente come chiave nella
hash. Se non è così, il programma utilizza la notazione La riga 6 isntalla il nome della città nell'array più appropriato.
push @array, $citta; ad eccezione del fatto che il nome Ho saltato un aspetto sottile. La riga 5 non è strettamente necessaria, e possiamo sbarazzarcene. 2 while (<>) { 3 chomp; 4 my ($citta, $nazione) = split /, /; 5 #### $tabella{$nazione} = [] unless exists $tabella{$nazione}; 6 push @{$tabella{$nazione}}, $citta; 7 } Se già esiste un elemento in Stiamo parlando di Perl, per cui fa la cosa giusta. In particolare, Perl si
accorge che volete inserire
Il RestoHo promesso di darvi il 90% dei benefici con il 10% dei dettagli. Il che vuol dire che ho tralasciato il 90% dei dettagli. Ora che avete una panoramica delle parti importanti, dovrebbe risultare facile la lettura di perlref, che parla del 100% dei dettagli. Alcuni punti importanti di perlref:
Forse preferirete proseguire con perllol, anziché perlref; parla, in dettaglio, di liste di liste e di array multidimensionali. Poi, potreste passare a perldsc; è il ``Ricettario delle Strutture Dati'', che mostra le ricette per stampare array di hash, hash di array e altri tipi di dato.
In sintesiOgnuno ha bisogno di strutture dati composte, e in Perl il modo di ottenerle sono i riferimenti. Ci sono quattro regole importanti per gestire i riferimenti. Due per creare riferimenti e due per usarli. Una volta imparate queste regole potete fare la maggior parte delle cose importanti che si fanno con i riferimenti.
CreditiAutore: Mark Jason Dominus, Plover Systems ( Questo articolo è apparso in origine in The Perl Journal ( http://www.tpj.com/ ) volume 3, numero 2. Ristampato dietro permesso. Il titolo originale dell'articolo è Comprendere i Riferimento Oggi.
Condizioni di DistribuzioneCopyright 1998 The Perl Journal. Questa documentazione è libera, potete redistribuirla e/o modificarla negli stessi termini di Perl stesso. Indipendentemente dalla modalità di distribuzione, tutti gli esempi di codice in questi file sono qui dichiarati di dominio pubblico. Vi è consentito (ed anzi siete incoraggiati a farlo) di usare questo codice nei vostri programmi per divertimento e profitto, come vi sembra meglio. Un semplice commento nel codice per dare credito sarebbe cortese ma non è richiesto.
TRADUZIONE
VersioneLa versione su cui si basa questa traduzione è ottenibile con: perl -MPOD2::IT -e print_pod perlreftut Per maggiori informazioni sul progetto di traduzione in italiano si veda http://pod2it.sourceforge.net/ .
TraduttoreTraduzione a cura di larsen, con adeguamenti di Flavio Poletti.
RevisoreRevisione a cura di bepi. Mon Jun 11 22:02:18 2012 |