Il Linguaggio Perl

Come un linguaggio parlato, il Perl è una combinazione di molte piccole parti legate l'una con l'altra. Al contrario del linguaggio parlato, dove sfumature, tono di voce ed intuizione consentono alle persone di comunicare nonostante piccole incompresioni e concetti fumosi, i computer ed il codice richiedono precisione. Potete scrivere codice Perl efficace anche senza conoscere tutti i dettagli di ogni caratteristica del linguaggio, ma dovete comprendere come esse interagiscono per scrivere bene del codice Perl.

Nomi

I nomi (o identificatori) sono dappertutto nei programmi Perl: variabili, funzioni, package, classi e perfino filehandle. Tutti questi nomi iniziano con una lettera o un underscore e possono includere opzionalmente qualunque combinazione di lettere, numberi e underscore. Quando la direttiva utf8 (Stringhe e Unicode) è attivata, potete usare negli identificatori qualunque carattere ammesso da UTF-8 in una parola. Questi sono tutti identificatori validi in Perl:

    my $nome;
    my @_nomi_privati;
    my %Da_Nomi_a_Indirizzi;

    sub unNomeBuffo3;

    # con use utf8; attivata
    package Ingy::Döt::Net;

Questi invece sono identificatori non validi:

    my $nome scorretto;
    my @3;
    my %~flag;

    package un-nome-in-stile-lisp;

I nomi esistono principalmente a beneficio del programmatore. Queste regole si applicano solo ai nomi che compaiono esplicitamente nel vostro codice sorgente, come sub prendi_torta oppure my $tostapane. Infatti, è il parser del Perl a controllare che le regole sui nomi siano rispettate.

La natura dinamica del Perl vi permette anche di riferirvi a delle entità attraverso nomi generati a runtime o dati in input al programma. Queste ricerche simboliche vi danno maggiore flessibilità al costo di una minore sicurezza. In particolare, invocando indirettamente delle funzioni e dei metodi o effettuando la ricerca dei simboli di un namespace, potete bypassare il parser del Perl.

Tutto questo può portare a del codice confuso. Come raccomanda molto efficacemente Mark Jason Dominus http://perl.plover.com/varvarname.html, usate piuttosto un hash (Hash) oppure una struttura dati annidata (Strutture Dati Annidate).

Nomi di Variabili e Sigilli

I nomi di variabile iniziano sempre con un sigillo (o simbolo) che indica il tipo del valore della variabile. Le variabili scalari (Scalari) usano il simbolo del dollaro ($). Le variabili array (Array) usano il simbolo chiocciola (@). Le variabili hash (Hash) usano il simbolo della percentuale (%):

    my $scalare;
    my @array;
    my %hash;

I sigilli costituiscono una sorta di namespace visuale per i nomi di variabili. È possibile dichiarare più variabili con lo stesso nome e tipi diversi, ma crea confusione:

    my ($cattiva_scelta, @cattiva_scelta, %cattiva_scelta);

Questo codice non confonde il Perl, ma confonde le persone che lo leggono.

I sigilli di Perl 5 sono varianti. Così come il contesto determina quanti elementi vi aspettate da un'operazione o quali tipi di dati vi aspettate di ottenere, i sigilli determinano il modo in cui manipolate i dati in una variabile. Per esempio, per accedere a un singolo elemento di un array o di un hash, dovete usare il sigillo scalare ($):

    my $elemento_di_hash  = $hash{ $chiave };
    my $elemento_di_array = $array[ $indice ]

    $hash{ $chiave }   = 'valore';
    $array[ $indice ]  = 'altro valore';

L'analogia con il contesto di numero è importante. Usare un elemento scalare di un aggregato come lvalue (parte di un assegnamento a sinistra del carattere =) impone un contesto scalare (Contesto) all'rvalue (parte a destra del carattere =).

In modo simile, un accesso a più elementi di un hash o di un array—una operazione nota come slicing—usa il simbolo chiocciola (@) e impone un contesto lista ... anche se la lista stessa ha zero o un solo elemento:

    my @elementi_di_hash  = @hash{ @chiavi };
    my @elementi_di_array = @array[ @indici ];

    my %hash;
    @hash{ @chiavi }     = @valori;

Il modo più affidabile di determinare il tipo di una variabile—scalare, array o hash—è di considerare le operazioni che le vengono applicate. Gli scalari supportano tutte le operazioni di base, come le manipolazioni di stringhe, numeriche e booleane. Gli array supportano accessi indicizzati che usano le parentesi quadre. Gli hash supportano accessi per chiave che usano le parentesi graffe.

Namespace

Perl fornisce un meccanismo per raggruppare funzioni e variabili correlate in un proprio spazio dei nomi univoco—i namespace (Package). Un namespace è una collezione di simboli con un suo nome. Perl permette di definire namespace multi-livello, i cui nomi sono composti con doppi due punti (::); per esempio, Dolci::Gelato si riferisce a una collezione di variabili e funzioni logicamente correlate, come cono() e versa_cioccolata_calda().

All'interno di un namespace, potete usare dei nomi abbreviati per i suoi membri. Al di fuori del namespace, vi riferite invece a un membro usando il suo nome qualificato. Ovvero, all'interno di Dolci::Gelato, aggiungi_praline() si riferisce alla stessa funzione di Dolci::Gelato::aggiungi_praline() al di fuori del namespace.

Oltre alle regole standard per i nomi, che si applicano anche ai nomi di package, per convenzione i nomi di package definiti dagli utenti iniziano con lettere maiuscole. Il core del Perl riserva infatti i nomi di package tutti minuscoli per le direttive (Direttive) come strict e warnings. Questa politica è imposta essenzialmente attraverso il rispetto delle linee guida della comunità.

Tutti i namespace in Perl 5 sono visibili a livello globale. Quando Perl deve fare la ricerca di un simbolo in Dolci::Gelato::Frigo, inizia col cercare nella symbol table main:: un simbolo che rappresenti il namespace Dolci::, quindi cerca al suo interno il namespace Gelato::, e così via. Il Frigo:: è quindi visibile dall'esterno del namespace Gelato::. Il fatto che i due namespace siano annidati è solo un meccanismo di memorizzazione, e non ha alcuna implicazione su ulteriori relazioni tra package padre e figlio o tra package fratelli. Sta al programmatore usare questo meccanismo per rendere evidenti le relazioni logiche tra entità—attraverso una buona scelta e organizzazione dei nomi.

Variabili

Una variabile in Perl è un'area per la memorizzazione di un valore (Valori). Mentre un programma triviale può manipolare direttamente dei valori, quasi tutti i programmi usano le variabili per semplificare la logica del codice. Una variabile rappresenta valori; è più semplice spiegare il teorema di Pitagora in termini di variabili a, b e c che dover intuire il suo principio da una lunga lista di valori validi. Questo concetto potrà sembrarvi banale, ma per programmare in modo efficace dovete padroneggiare l'arte di bilanciare tra il generico e riusabile e lo specifico.

Scope delle Variabili

Le variabili sono visibili alle diverse parti del vostro programma in base al loro scope (Scope). Molte delle variabili che incontrerete hanno uno scope lessicale (Scope Lessicale). I file sorgente forniscono uno scope lessicale, mentre una dichiarazione di package non crea di per sé un nuovo scope:

    package Negozio::Giocattoli;

    my $sconto = 0.10;

    package Negozio::Musica;

    # $sconto ancora visibile
    say "Il nostro sconto è attualmente $sconto!";

A partire da Perl 5.14, potete associare un blocco a una dichiarazione package. Questa sintassi fornisce effettivamente uno scope lessicale:

    package Negozio::Giocattoli
    {
        my $sconto = 0.10;
    }

    package Negozio::Musica
    {
        # $sconto non disponibile
    }

    package Negozio::GiochiDaTavolo;

    # $sconto sempre non disponibile

Sigilli delle Variabili

Il sigillo della variabile in una dichiarazione determina il tipo della variabile: scalare, array o hash. Il sigillo usato quando si accede alla variabile varia invece in base a ciò che volete fare con la variabile. Per esempio, dichiarate un array con @valori. Accedete al suo primo elemento—un singolo valore—con $valori[0]. E accedete a una lista di valori dentro l'array con @valori[ @indici ].

Variabili Anonime

In Perl non è richiesto che le variabili abbiano un nome. I nomi servono ad aiutare voi, i programmatori, a tener traccia di una $mela, delle @scatole o dei %ristoranti_economici. Le variabili create senza un nome dal vostro codice sorgente sono dette variabili anonime. L'unico modo per accedere a una variabile anonima è per riferimento (Riferimenti).

Variabili, Tipi e Coercizione

Una variabile in Perl 5 rappresenta sia un valore (un costo in euro, dei tipi di pizza disponibili, dei negozi di chitarre con i loro numeri di telefono) che il contenitore che memorizza tale valore. Il sistema dei tipi di Perl gestisce sia i tipi valore che i tipi contenitore. Mentre il tipo contenitore di una variabile—scalare, array o hash—non può cambiare, Perl è flessibile riguardo al tipo valore. Potete memorizzare una stringa in una variabile in una data linea di codice, assegnare un numero alla stessa variabile nella linea successiva e quindi riassegnarle il riferimento a una funzione (Riferimenti a Funzioni).

Eseguire su una variabile una operazione che impone uno specifico tipo valore può dar luogo a una coercizione (Coercizione) dal precedente tipo valore della variabile stessa.

Per esempio, il modo ufficialmente documentato di determinare il numero di elementi in un array è di valutare l'array in contesto scalare (Contesto). Dato che una variabile scalare può sempre e solo contenere uno scalare, assegnare un array a uno scalare impone il contesto scalare all'operazione, e un array valutato in contesto scalare restituisce il numero di elementi nell'array:

    my $conteggio = @elementi;

Queste relazioni tra tipi delle variabili, sigilli e contesto sono di importanza fondamentale.

Valori

La struttura di un proramma è fortemente influenzata dal modo in cui modellate i vostri dati con le variabili appropriate.

Mentre le variabili permettono la manipolazione astratta dei dati, i valori che esse contengono rendono i programmi utili e concreti. Più questi valori sono accurati, migliori sono i vostri programmi. I valori rappresentano dati—il nome e l'indirizzo di vostra zia, la distanza tra il vostro ufficio e un campo da golf sulla Luna, o il peso di tutti i biscotti che avete mangiato lo scorso anno. All'interno del vostro programma, le regole sul formato di tali dati sono spesso rigide. Dei programmi efficaci necessitano di modi efficaci (ovvero semplici, veloci, compatti, efficienti) per rappresentare i propri dati.

Stringhe

Una stringa è un dato testuale o binario senza particolari restrizioni di formato o contenuto. Potrebbe essere il vostro nome, il contenuto di un file immagine o lo stesso vostro programma. Una stringa ha un significato nel programma solo quando gliene attribuite uno.

Per rappresentare una stringa nel vostro programma, racchiudetela tra una coppia di caratteri di quotatura. I delimitatori di stringa più comuni sono i singoli e doppi apici:

    my $nome      = 'Donner Odinson, Portatore di Disperazione';
    my $indirizzo = "Stanza 539, Bilskirnir, Valhalla";

I caratteri in una stringa a singola quotatura rappresentano se stessi letteralmente, con due eccezioni. Per inserire un apice singolo in una stringa a singola quotatura fatelo precedere da un carattere backslash di escape:

    my $ricorda = 'L\'apice va preceduto '
                . 'da un carattere di escape!';

Dovete precedere con l'escape anche un backslash alla fine della stringa per evitare che esso faccia da escape all'apice finale producendo un errore di sintassi:

    my $eccezione = 'Questa stringa termina con un '
                  . 'escape, non con un apice: \\';

Tutti gli altri backslash vengono interpretati letteralmente, a meno che ve ne siano due in sequenza, nel qual caso il primo fa da escape al secondo:

    is('Modern \ Perl', 'Modern \\ Perl',
        'escape del backslash tra apici singoli');

Una stringa a doppia quotatura ha molti più caratteri speciali a disposizione. Per esempio, potete codificare nella stringa dei caratteri di spaziatura altrimenti invisibili:

    my $tab       = "\t";
    my $newline   = "\n";
    my $carriage  = "\r";
    my $formfeed  = "\f";
    my $backspace = "\b";

Questo esempio mostra un principio utile: la sintassi usata per dichiarare una stringa può variare. Potete rappresentare un tab all'interno di una stringa sia con l'escape \t che digitando direttamente un tab. Per ciò che riguarda il Perl, le due stringhe funzionano allo stesso modo, anche se le rappresentazioni specifiche della stringa differiscono nel codice sorgente.

La dichiarazione di una stringa può contenere diverse linee di testo delimitate da newline; queste due dichiarazioni sono equivalenti:

    my $con_escape = "due\nlinee";
    my $letterale  = "due
    linee";
    is $con_escape, $letterale, 'equivalenza \n e newline';

Le sequenze di escape sono spesso più facili da leggere della spaziatura equivalente.

Le stringhe Perl hanno lunghezza variabile. Quando le manipolate e modificate, il Perl cambia la loro dimensione in modo appropriato. Per esempio, potete combinare diverse stringhe in una stringa più grande con l'operatore . di concatenazione:

    my $gattino = 'Micio' . ' ' . 'Miao';

A tutti gli effetti, è come se aveste inizializzato la stringa tutta insieme.

In una stringa a doppia quotatura potete anche interpolare il valore di una variabile scalare o i valori di un array, in modo tale che il contenuto attuale della variabile diventi parte della stringa come se le aveste concatenate:

    my $fatto = "$nome vive a $indirizzo!";

    # equivalente a
    my $fatto = $nome . ' vive a ' . $indirizzo . '!';

Per inserire un doppio apice in una stringa a doppia quotatura fatelo precedere da un carattere di escape (ovvero, un backslash):

    my $citazione = "\"Ahia,\", gridò.  \"Fa male!\"";

Quando troppi backslash creano confusione, usate un operatore di quotatura alternativo con cui potete scegliere un diverso delimitatore di stringa. L'operatore q indica singola quotatura, mentre l'operatore qq si comporta come una doppia quotatura. Il carattere che segue l'operatore determina quali sono i caratteri che delimitano la stringa. Se tale carattere è il primo di una coppia di caratteri bilanciati—come aperta e chiusa graffa—il corrispondente carattere di chiusura sarà il delimitatore di fine stringa. Altrimenti, lo stesso carattere fungerà da delimitatore sia di inizio che di fine stringa.

    my $citazione = qq{"Ahia", disse.  "Fa male!"};
    my $ricorda   =  q^L'apice singolo non va quotato!^;
    my $reclamo   =  q{È un po' troppo presto per svegliarsi.};

Quando dichiarare una stringa complessa con molti caratteri di escape diventa noioso, usate la sintassi heredoc per assegnare una o più linee a una stringa:

    my $estratto =<<'FINE_ESTRATTO';

    Egli alzò lo sguardo. "Il tempo non è mai dalla nostra parte, figlio mio.
    Non ne vedi l'ironia? Tutto ciò che essi conoscono è il cambiamento.
    Il cambiamento è la sola costante su cui tutti loro concordano.
    Noi, invece, nati fuori dal tempo, restiamo perfetti e
    perfettamente auto-coscienti. E possiamo accettare il cambiamento solo
    quando noi stessi lo perseguiamo. È contro la nostra natura: ci ribelliamo
    contro il cambiamento. Dobbiamo forse considerarli
    superiori per questo?"
    FINE_ESTRATTO

La sintassi di <<'FINE_ESTRATTO' ha tre parti. Le doppie parentesi angolari introducono l'heredoc. Gli apici determinamo se l'heredoc si comporta come una stringa a singola o doppia quotatura. Il comportamento di default è quello della doppia quotatura con la relativa interpolazione. FINE_ESTRATTO è un identificatore arbitrario che il parser Perl 5 usa come delimitatore finale.

Fate attenzione; indipendentemente dall'indentazione della dichiarazione dell'heredoc, il delimitatore finale deve essere all'inizio della linea:

    sub una_funzione {
        my $ingredienti =<<'FINE_INGREDIENTI';
        Due uova
        Una tazza di farina
        Due etti di burro
        Un quarto di cucchiaino di sale
        Una tazza di latte
        Un pizzico di vaniglia
        Condimento a piacere
    FINE_INGREDIENTI
    }

Usare una stringa in un contesto diverso da quello stringa causa una coercizione (Coercizione).

Stringhe e Unicode

Unicode è un sistema per rappresentare tutti i caratteri delle lingue scritte del mondo. Mentre gran parte dei testi in inglese usano un insieme di soli 127 caratteri (che richiedono sette bit di memoria e stanno comodamente negli otto bit di un byte), sarebbe naïve pensare che non vi possa servire un giorno o l'altro una dieresi.

Le stringhe in Perl 5 possono rappresentare due tipi di dati distinti anche se correlati:

Le Parole Contano

Perché ottetti e non byte? L'assunzione che un carattere possa stare dentro un byte può essere causa di problemi senza fine con Unicode. Separate quindi l'idea di spazio in memoria da quella della rappresentazione dei caratteri.

Le stringhe Unicode e binarie sono simili. Ciascuna ha una length(). Ciascuna supporta le operazioni standard sulle stringhe come la concatenazione, lo splicing e l'applicazione di espressioni regolari. Ogni stringa che non contenga dati binari puri contiene dati testuali, e dovrebbe quindi essere una sequenza di caratteri Unicode.

Tuttavia, dato che il vostro sistema operativo reppresenta i dati su disco (o in input dall'utente o dalla rete) come sequenze di ottetti, Perl non può sapere se i dati che leggete costituiscono un file immagine o un documento di testo o qualunque altra cosa. Per default, Perl tratta tutti i dati in input come sequenze di ottetti. Tocca a voi assegnare un significato specifico a tali dati.

Codifica dei Caratteri

Una stringa Unicode è una sequenza di ottetti che rappresenta una sequenza di caratteri. Una codifica Unicode mappa sequenze di ottetti in sequenze di caratteri. Alcune codifiche, come UTF-8, possono codificare tutti i caratteri dell'insieme di caratteri Unicode. Altre codifiche rappresentano un sottoinsieme dei caratteri Unicode. Per esempio, l'ASCII codifica un testo in inglese comune senza caratteri accentati, mentre Latin-1 può rappresentare testo nella maggior parte delle lingue che usano l'alfabeto latino.

Per evitare problemi con Unicode, decodificate e codificate sempre dalla/alla codifica appropriata durante l'input e l'output del vostro programma.

Uno Standard in Evoluzione

Perl 5.12 supporta lo standard Unicode 5.2, mentre Perl 5.14 supporta Unicode 6.0. Se avete bisogno di tenere conto delle differenze tra le versioni di Unicode, probabilmente conoscete già il sito http://unicode.org/versions/.

Unicode nei Vostri Filehandle

Quando comunicate al Perl che uno specifico filehandle (File) lavora con testo codificato, Perl convertirà automaticamente gli ottetti in input in stringhe Unicode. Per ottenere questo, aggiungete un layer di IO al modo della funzione nativa open. Un layer di IO si interpone tra il programma e l'input o l'output convertendo i dati. Nel seguente esempio, il layer :utf8 decodifica dei dati UTF-8:

    use autodie;

    open my $fh, '<:utf8', $file_di_testo;

    my $stringa_unicode = <$fh>;

Con binmode, potete anche modificare un filehandle esistente, sia per l'input che per l'output:

    binmode $fh, ':utf8';
    my $stringa_unicode = <$fh>;

    binmode STDOUT, ':utf8';
    say $stringa_unicode;

Senza il modo utf8, stampare delle stringhe Unicode su un filehandle provoca un warning (Wide character in %s), perché il file contiene ottetti, e non caratteri Unicode.

Unicode nei Vostri Dati

Il modulo core Encode fornisce una funzione di nome decode() per convertire uno scalare contenente dei dati in una stringa Unicode. La corrispondente funzione encode() converte dalla codifica interna del Perl alla codifica di output desiderata:

    my $da_utf8  = decode('utf8', $dati);
    my $a_latin1 = encode('iso-8859-1', $stringa);

Unicode nei Vostri Programmi

Potete includere caratteri Unicode nei vostri programmi in tre modi. Il modo più semplice è quello di usare la direttiva utf8 (Direttive), che indica al parser Perl di interpretare il resto del file di codice sorgente con la codifica UTF-8. Ciò vi permette di usare caratteri Unicode nelle stringhe e negli identificatori:

    use utf8;

    sub da_£_a_¥ { ... }

    my $yen = da_£_a_¥('1000£');

Per poter scrivere questo codice, il vostro editor di testo deve supportare UTF-8 e dovete salvare il file con la codifica appropriata.

All'interno di stringhe a doppia quotatura, potete usare la sequenza di escape Unicode per rappresentare la codifica dei caratteri. La sintassi \x{} rappresenta un carattere singolo; mettete il codice Unicode del carattere in esadecimale dentro alle parentesi graffe:

    my $thorn_con_escape = "\x{00FE}";

Alcuni caratteri Unicode hanno dei nomi, che spesso sono più facili da leggere dei codici Unicode. Usate la direttiva charnames per attivarli e la sequenza di escape \N{} per riferirvi ad essi:

    use charnames ':full';
    use Test::More tests => 1;

    my $thorn_con_escape = "\x{00FE}";
    my $thorn_per_nome   = "\N{LATIN SMALL LETTER THORN}";

    is $thorn_con_escape, $thorn_per_nome,
        'controllo di equivalenza carattere thorn';

Potete usare \x{} e \N{} all'interno di espressioni regolari e in ogni altro punto dove potete legittimamente inserire una stringa o un carattere.

Conversione Implicita

Molti dei problemi con Unicode in Perl nascono dal fatto che una stringa può essere sia una sequenza di ottetti che una sequenza di caratteri. Perl vi permette di combinare questi due tipi attraverso l'uso delle conversioni implicite. Quando queste conversioni sono sbagliate, raramente lo sono in modo ovvio.

Quando Perl concatena una sequenza di ottetti con una sequenza di caratteri Unicode, decodifica implicitamente la sequenza di ottetti usando la codifica Latin-1. La stringa risultante conterrà caratteri Unicode. Quando stampate dei caratteri Unicode, Perl codifica la stringa usando UTF-8, perché Latin-1 non può rappresentare l'intero insieme di caratteri Unicode—Latin-1 è un sottoinsieme di UTF-8.

Questa asimmetria può dar luogo a stringhe Unicode codificate con UTF-8 in output e decodificate con Latin-1 in input.

Peggio ancora, quando il testo contiene solo caratteri dell'inglese senza accento, il bug rimane nascosto—dato che entrambe le codifiche hanno la stessa rappresentazione di ogni carattere.

    my $ciao     = "Ciao, ";
    my $saluto   = $ciao . $nome;

Se $nome contiene un nome in alfabeto inglese come Alice non si riscontra nessun problema, dato che la rappresentazione Latin-1 è uguale alla rappresentazione UTF-8. Se invece $name contiene un nome come José, ci sono diverse possibilità:

Ci sono diversi scenari anche per il letterale stringa:

Se sia $ciao che $nome sono stringhe Unicode, la loro concatenazione produce un'altra stringa Unicode.

Se entrambe le stringhe sono sequenze di ottetti, Perl le concatenerà in una nuova sequenza di ottetti. Se entrambi i valori contengono ottetti di una stessa codifica—per esempio, Latin-1—la concatenazione funzionerà correttamente. Se invece gli ottetti appartengono a diverse codifiche, per esempio una concatenazione di dati UTF-8 a dati Latin-1, la sequenza di ottetti risultante è priva di senso per entrambe le codifiche. Questo potrebbe succedere se l'utente avesse immesso un nome come stringa UTF-8 e il saluto fosse una costante stringa in Latin-1, ma il programma non avesse decodificato nessuna delle due.

Se solo uno dei valori è una stringa Unicode, Perl decodificherà l'altro come un dato Latin-1. Se questa non è la codifica corretta, i caratteri Unicode risultanti saranno errati. Per esempio, se l'input dell'utente fosse un dato UTF-8 e la costante stringa fosse Unicode, il nome verrebbe decodificato erroneamente come i cinque caratteri Unicode José (sic) invece di José perché i dati UTF-8 hanno un altro significato quando sono decodificati come dati Latin-1.

Vedete perldoc perluniintro per una spiegazione molto più dettagliata di Unicode, delle codifiche e di come gestire i dati in ingresso e in uscita in un mondo Unicode Per avere molti più dettagli su una gestione efficace di Unicode in ogni parte dei vostri programmi, vedete la risposta di Tom Christiansen a "Why does Modern Perl avoid UTF-8 by default?" http://stackoverflow.com/questions/6162484/why-does-modern-perl-avoid-utf-8-by-default/6163129#6163129.

Numeri

Perl supporta i numeri sia come valori interi che a virgola mobile. Potete rappresentarli anche con la notazione scientifica e in forma binaria, ottale ed esadecimale:

    my $intero      = 42;
    my $float       = 0.007;
    my $float_sci   = 1.02e14;
    my $binario     = 0b101010;
    my $ottale      = 052;
    my $esadecimale = 0x20;

I caratteri in grassetto sono i prefissi numerici rispettivamente per le notazioni binaria, ottale ed esadecimale. Ricordate che uno zero iniziale in un intero indica sempre la forma ottale.

Quando 1.99 + 1.99 fa 4

Anche se in Perl 5 potete scrivere esplicitamente valori a virgola mobile perfettamente accurati, Perl 5 li memorizza internamente in forma binaria. Questa rappresentazione a volte è causa di specifiche imprecisioni; consultate perldoc perlnumber per maggiori dettagli.

Non potete usare delle virgole per separare le migliaia nei letterali numerici, dato che il parser interpreta le virgole come operatori. Usate invece gli underscore. Il parser li tratterà come caratteri invisibili; per chi legge il codice invece non lo sono. Queste istruzioni sono equivalenti:

    my $miliardo = 1000000000;
    my $miliardo = 1_000_000_000;
    my $miliardo = 10_0_00_00_0_0_0;

Considerate qual è l'alternativa più leggibile.

Grazie alla coercizione (Coercizione), raramente i programmatori Perl devono preoccuparsi di convertire in numeri un testo letto dall'esterno del programma. Perl tratta tutto ciò che sembra un numero come un numero in contesto numerico. Nelle rare occasioni in cui volete sapere se qualcosa sembra un numero al Perl, usate la funzione looks_like_number del modulo core Scalar::Util. Questa funzione restituisce il valore vero se Perl considera come numerico l'argomento passato.

Il modulo CPAN Regexp::Common fornisce molte espressioni regolari ben testate per identificare tipi validi più specifici di valori numerici (numero naturale, intero, a virgola mobile).

Undef

Il valore undef del Perl 5 rappresenta un valore non assegnato, indefinito e sconosciuto. Le variabili scalari dichiarate ma non definite contengono undef:

    my $nome = undef;   # assegnamento superfluo
    my $rango;          # contiene anche undef

In contesto booleano, undef viene valutato come falso. Valutare undef in contesto stringa—ad esempio interpolarlo in una stringa—causa un warning di uninitialized value:

    my $non_definito;
    my $definito = $non_definito . '... e così via';

... produce:

    Use of uninitialized value $non_definito in
    concatenation (.) or string...

La funzione nativa defined restituisce vero se il suo operando viene valutato come valore definito (ovvero qualunque cosa tranne undef):

    my $stato = 'ho il raffreddore';

    say defined $stato;  # 1, che rappresenta il valore vero
    say defined undef;   # stringa vuota; un valore falso

La Lista Vuota

Quando compare a destra in un assegnamento, il costrutto () rappresenta una lista vuota. In contesto scalare, viene valutato come undef. In contesto lista, è semplicemente una lista vuota. Quando invece compare a sinistra in un assegnamento, il costrutto () impone il contesto lista. Per contare il numero di elementi restituiti da una espressione in contesto lista senza usare una variabile temporanea, usate l'idioma (Idiomi):

    my $conteggio = () = tutti_i_miei_cappelli();

Dato che l'operatore di assegnamento è associativo a destra (Associatività), Perl valuta per primo il secondo assegnamento chiamando tutti_i_miei_cappelli() in contesto lista. Questa chiamata restituisce una lista.

L'assegnamento alla lista vuota fa perdere tutti i valori della lista, ma tale assegnamento ha luogo in contesto scalare, che valuta il numero di elementi nella parte destra dell'assegnamento. Di conseguenza, $conteggio contiene il numero di elementi nella lista restituita da tutti_i_miei_cappelli().

Se per il momento trovate questo concetto un po' confuso, non preoccupatevi. Man mano che capirete come le funzionalità di progetto fondamentali del Perl si incastrano tra loro nella pratica, tutto diventerà più chiaro.

Liste

Una lista è un gruppo di una o più espressioni separate dalla virgola. Le liste possono comparire letteralmente nel codice sorgente come valori:

    my @primi_fib = (1, 1, 2, 3, 5, 8, 13, 21);

... come target di un assegnamento:

    my ($package, $nomefile, $linea) = chiamante();

... o come liste di espressioni:

    say nome(), ' => ', anni();

Non sono le parentesi tonde che creano una lista. È la virgola che la crea. Dove sono presenti in questi esempi, le parentesi raggruppano espressioni per modificarne la precedenza (Precedenza).

Usate l'operatore di intervallo per creare liste di letterali in forma compatta:

    my @caratteri = 'a' .. 'z';
    my @contatore = 13 .. 27;

Usate l'operatore qw() per spezzare un letterale stringa con i caratteri di spaziatura e produrre una lista di stringhe:

    my @stooges = qw( Larry Curly Moe Shemp Joey Kenny );

Nessun Commento per Favore

Perl genera un warning se qw() contiene una virgola o il carattere di commento (#), perché non solo tali caratteri sono rari in un qw(), ma la loro presenza indica normalmente una svista.

Le liste possono occorrere (e spesso lo fanno) come risultati di espressioni, ma queste liste non compaiono letteralmente nel codice sorgente.

Le liste e gli array non sono interscambiabili in Perl. Le liste sono valori. Gli array sono contenitori. Potete memorizzare una lista in un array e potete forzare la conversione di un array in una lista, ma essi restano entità separate. Per esempio, l'indicizzazione di una lista occorre sempre in contesto lista. L'indicizzazione di un array può occorrere sia in contesto scalare (per un singolo elemento) che in contesto lista (per una slice):

    # non preoccupatevi dei dettagli per ora
    sub contesto
    {
        my $contesto = wantarray();

        say defined $contesto
             ? $contesto
                 ? 'lista'
                 : 'scalare'
             : 'void';
        return 0;
    }

    my @slice_di_lista  = (1, 2, 3)[contesto()];
    my @slice_di_array  = @slice_di_lista[contesto()];
    my $indice_di_array = $slice_di_array[contesto()];

    say contesto(); # contesto lista
    contesto();     # contesto void

Controllo di Flusso

Il controllo di flusso di base del Perl è molto semplice. L'esecuzione del programma comincia dall'inizio (la prima linea del file da eseguire) e prosegue fino alla fine:

    say 'All'inizio';
    say 'In mezzo';
    say 'Alla fine';

Le direttive di controllo di flusso del Perl modificano l'ordine di esecuzione—ovvero che cosa avviene al prossimo passo nel programma—in base ai valori delle loro espressioni.

Direttive di Scelta

La direttiva if esegue l'azione associata solo quando la sua espressione condizionale ha valore vero:

    say 'Ciao, Roberto!' if $nome eq 'Roberto';

La forma postfissa è adeguata in caso di espressioni semplici. La forma a blocco raggruppa diverse espressioni in una singola unità:

    if ($nome eq 'Roberto')
    {
        say 'Ciao, Roberto!';
        trovato_roberto();
    }

Mentre la forma a blocco richiede che la condizione sia tra parentesi, la forma postfissa non lo richiede.

L'espressione condizionale può consistere di diverse sotto-espressioni, purché esse compongano un'unica espressione principale:

    if ($nome eq 'Roberto' && not salutato_roberto())
    {
        say 'Ciao, Roberto!';
        trovato_roberto();
    }

Nella forma postfissa, aggiungere delle parentesi può aiutare a chiarire il significato del codice al costo di una minor eleganza visiva:

    saluta_roberto() if ($nome eq 'Roberto' && not salutato_roberto());

La direttiva unless è una forma negata di if. Perl esegue l'azione quando l'espressione condizionale è falsa:

    say "Tu non sei Roberto!" unless $nome eq 'Roberto';

Come if, anche unless ha una forma a blocco, anche se molti programmatori la evitano poiché diventa rapidamente difficile da leggere in presenza di condizionali complessi:

    unless (anno_bisestile() and luna_piena())
    {
        spassatela();
        fai_capriole();
    }

unless è particolarmente adatta ad essere usata con condizionali postfissi, specialmente per la validazione dei parametri delle funzioni (Validazione Postfissa dei Parametri):

    sub spassatela
    {
        return unless @_;

        for my $canzone (@_) { ... }
    }

Entrambe le forme a blocco di if e unless accettano la direttiva else, che specifica il codice da eseguire quando l'espressione condizionale non ha valore vero (per if) o falso (per unless):

    if ($nome eq 'Roberto')
    {
        say 'Ciao, Roberto!';
        accogli_utente();
    }
    else
    {
        say "Non ti conosco.";
        ignora_utente();
    }

I blocchi else vi permettono di riscrivere i condizionali if e unless l'uno nei termini dell'altro:

    unless ($nome eq 'Roberto')
    {
        say "Non ti conosco.";
        ignora_utente();
    }
    else
    {
        say 'Ciao, Roberto!';
        accogli_utente();
    }

Tuttavia, la doppia negazione implicita nell'uso di unless con un blocco else può creare confusione. Questo esempio potrebbe essere l'unico posto dove vi capiterà di vederlo.

Così come vi fornisce sia if che unless per permettervi di esprimere i vostri condizionali nel modo più leggibile, il Perl vi permette anche di scegliere tra operatori condizionali positivi e negativi:

    if ($nome ne 'Roberto')
    {
        say "Non ti conosco.";
        ignora_utente();
    }
    else
    {
        say 'Ciao, Roberto!';
        accogli_utente();
    }

... anche se la doppia negazione implicita nella presenza del blocco else suggerirebbe di invertire il condizionale.

Una o più direttive elsif possono seguire un blocco if e precedere un singolo else:

    if ($nome eq 'Roberto')
    {
        say 'Ciao, Roberto!';
        accogli_utente();
    }
    elsif ($nome eq 'Giacomo')
    {
        say 'Ciao, Giacomo!';
        accogli_utente();
    }
    else
    {
        say "Non sei mio zio.";
        ignora_utente();
    }

Anche un blocco unless può essere seguito da un blocco elsif Buona fortuna se volete capirci qualcosa!. Invece non esiste elseunless.

Scrivere else if costituisce un errore di sintassi Larry preferisce elsif per ragioni estetiche, come nell'antica arte del linguaggio Ada.:

    if ($nome eq 'Riccardo')
    {
        say 'Ciao, cugino!';
    }

    # attenzione; errore di sintassi
    else if ($nome eq 'Cristina')
    {
        say 'Ciao, cugina!';
    }

L'Operatore Condizionale Ternario

L'operatore condizionale ternario valuta un'espressione condizionale e sceglie tra due alternative:

    my $suffisso_temporale = dopo_pranzo($tempo)
                           ? 'pomeriggio'
                           : 'mattino';

L'espressione condizionale precede il carattere punto interrogativo (?) e il carattere due punti (:) separa le due alternative. Le alternative sono espressioni di complessità arbitraria—incluse altre espressioni condizionali ternarie.

Cortocircuiti

Il Perl può cortocircuitare parti di espressioni condizionali complesse. Quando Perl è in grado di determinare che un'espressione complessa è vera o falsa senza aver ancora valutato tutte le sue sottoespressioni, le sottoespressioni rimanenti non vengono più valutate. Un esempio dovrebbe aiutare a chiarire:

    say "Entrambi veri!" if ok( 1, 'sottoespressione uno' )
                         && ok( 1, 'sottoespressione due' );

    done_testing();

Il valore di ritorno di ok() (Testing) è il valore booleano ottenuto valutando il suo primo argomento, quindi questo codice stampa:

    ok 1 - sottoespressione uno
    ok 2 - sottoespressione due
    Entrambi veri!

Quando la prima sottoespressione—la prima chiamata a ok—ha valore vero, Perl deve valutare la seconda sottoespressione. Se invece la prima sottoespressione avesse valore falso, non sarebbe necessario valutare le sottoespressioni successive, dato che l'intera espressione non potrà comunque essere vera:

    say "Entrambi veri!" if ok( 0, 'sottoespressione uno' )
                         && ok( 1, 'sottoespressione due' );

Questo esempio stampa:

    not ok 1 - sottoespressione uno

Sebbene la seconda sottoespressione sia ovviamente vera, Perl non la valuta. Lo stesso tipo di cortocircuito si applica alle operazioni di or logico:

    say "Almeno uno vero!" if ok( 1, 'sottoespressione uno' )
                           || ok( 1, 'sottoespressione due' );

Questo esempio stampa:

    ok 1 - sottoespressione uno
    Almeno uno vero!

Dato il successo della prima sottoespressione, Perl può evitare di valutare la seconda sottoespressione. Se la prima sottoespressione fosse stata falsa, il risultato della valutazione della seconda sottoespressione avrebbe determinato il risultato della valutazione dell'intera espressione.

Oltre a permettervi di evitare computazioni potenzialmente costose, i cortocircuiti possono aiutarvi a evitare errori e warning, come nel caso in cui l'uso di un valore non definito potrebbe causare un warning:

    my $barbecue;
    if (defined $barbecue and $barbecue eq 'salsiccia') { ... }

Contesto per le Direttive Condizionali

Le direttive condizionali—if, unless e l'operatore condizionale ternario—valutano tutte un'espressione in contesto booleano (Contesto). Così come gli operatori eq, ==, ne e != producono tutti un risultato booleano quando vengono valutati, Perl converte i risultati di altre espressioni—inclusi variabili e valori—in forma booleana.

Perl 5 non ha un unico valore vero, né un unico valore falso. Tutti i numeri che hanno valore 0 rappresentano il valore falso. Tra questi: 0, 0.0, 0e0, 0x0, ecc. La stringa vuota ('') e la stringa '0' hanno valore falso, ma non le stringhe '0.0', '0e0', ecc. L'idioma '0 ma vero' valuta a 0 in contesto numerico e a vero in contesto booleano, grazie al suo contenuto come stringa.

Sia la lista vuota che undef hanno valore falso. Gli array e gli hash vuoti restituiscono il numero 0 in contesto scalare, e quindi hanno valore falso in contesto booleano. Un array che contiene un unico elemento—anche se fosse undef—valuta a vero in contesto booleano. Un hash che contiene qualche elemento—anche una chiave con valore associato undef—valuta a vero in contesto booleano.

Più Controllo suo Contesto

Il modulo CPAN Want vi permette di individuare un contesto booleano all'interno delle vostre funzioni. La direttiva overloading del core (Overloading) vi permette di specificare che cosa devono produrre i vostri tipi di dati quando sono valutati in diversi contesti.

Direttive di Ciclo

Perl fornisce diverse direttive di ciclo e iterazione. Il ciclo in stile foreach valuta un'espressione che produce una lista e esegue un'istruzione o un blocco fino a quando ha consumato tale lista:

    foreach (1 .. 10)
    {
        say "$_ * $_ = ", $_ * $_;
    }

Questo esempio usa l'operatore di intervallo per produrre una lista di interi da uno a dieci inclusi. La direttiva foreach cicla su questi numeri, settando la variabile topic $_ (La Variabile Scalare di Default) a ciascuno di essi a turno. Perl esegue il blocco per ogni intero e stampa il suo quadrato.

foreach e for

Molti programmatori Perl si riferiscono alle iterazioni come cicli foreach, ma Perl tratta i nomi foreach e for in modo interscambiabile. È il codice che li accompagna a determinare il tipo e comportamento del ciclo.

Analogamente a if e unless, questo ciclo ha forma postfissa:

    say "$_ * $_ = ", $_ * $_ for 1 .. 10;

Un ciclo for può specificare il nome di una variabile anziché usare la variabile topic:

    for my $i (1 .. 10)
    {
        say "$i * $i = ", $i * $i;
    }

Quando un ciclo for usa una variabile iteratore, lo scope della variabile è l'interno del loop. Perl setta questa variabile lessicale al valore di ciascun elemento su cui opera l'iterazione. Perl non modifica la variabile topic ($_). Se avete dichiarato una variabile lessicale $i nello scope più esterno, il suo valore rimane intatto al di fuori del ciclo:

    my $i = 'mucca';

    for my $i (1 .. 10)
    {
        say "$i * $i = ", $i * $i;
    }

    is( $i, 'mucca', 'Valore intatto nello scope esterno' );

Questa localizzazione avviene anche se non ridichiarate la variabile iteratore come lessicale ... ma siete caldamente invitati a dichiarare le vostre variabili iteratore come lessicali per ridurne lo scope.:

    my $i = 'cavallo';

    for $i (1 .. 10)
    {
        say "$i * $i = ", $i * $i;
    }

    is( $i, 'cavallo', 'Valore intatto nello scope esterno' );

Iterazione e Alias

Il ciclo for effettua un aliasing della variabile iteratore ai valori su cui opera l'iterazione in modo che ogni modifica al valore dell'iteratore modifica anche il valore corrente dell'iterazione:

    my @numeri = 1 .. 10;

    $_ **= 2 for @numeri;

    is( $numeri[0], 1, '1 * 1 vale 1' );
    is( $numeri[1], 4, '2 * 2 vale 4' );

    ...

    is( $numeri[9], 100, '10 * 10 vale 100' );

L'aliasing funziona anche con la forma a blocco del ciclo for:

    for my $num (@numeri)
    {
        $num **= 2;
    }

... e con le iterazioni che usano la variabile topic:

    for (@numeri)
    {
        $_ **= 2;
    }

Tuttavia, non potete usare l'aliasing per modificare valori costanti:

    for (qw( Qui Quo Qua ))
    {
        $_++;
        say;
    }

In questo caso, il Perl solleverà un'eccezione relativa al tentativo di modifica di valori read-only.

Potrà succedervi occasionalmente di vedere l'uso del for con una singola variabile scalare, allo scopo di effettuare un aliasing di $_ a tale variabile:

    for ($input_utente)
    {
        s/\A\s+/;       # scarta spaziatura iniziale
        s/\s+\z/;       # scarta spaziatura finale

        $_ = quotemeta; # aggiungi escape a caratteri speciali
    }

Iterazione e Scope

Lo scope della variabile topic usata come iteratore è una causa comune di confusione. Considerate una funzione scombina_topic() il cui scopo è di modificare $_. Se il codice che itera su una lista chiama scombina_topic() senza proteggere $_, ci sarà poi da divertirsi col debugging:

    for (@valori)
    {
        scombina_topic();
    }

    sub scombina_topic
    {
        s/pippo/pluto/;
    }

Se proprio dovete usare $_ anziché un'altra variabile, rendete la variabile topic lessicale con my $_:

    sub scombina_topic
    {
        # era $_ = shift;
        my $_ = shift;

        s/pippo/pluto/;
        s/paperino/topolino/;

        return $_;
    }

Anche l'uso di una variabile iteratore con un nome previene gli aliasing indesiderati di $_.

Il Ciclo For in Stile C

Il ciclo for in stile C vi richiede di gestire le condizioni dell'iterazione:

    for (my $i = 0; $i <= 10; $i += 2)
    {
        say "$i * $i = ", $i * $i;
    }

In questo costrutto dovete assegnare esplicitamente a una variabile iteratore, dato che esso non effettua né aliasing né assegnamenti alla variabile topic. Mentre una variabile dichiarata all'interno del costrutto di ciclo ha come scope il blocco lessicale del ciclo, una variabile dichiarata all'esterno del costrutto di ciclo non viene lessicalizzata:

    my $i = 'maiale';

    for ($i = 0; $i <= 10; $i += 2)
    {
        say "$i * $i = ", $i * $i;
    }

    isnt( $i, 'maiale', '$i sovrascritto con un numero' );

Il costrutto di ciclo può avere tre sottoespressioni. La prima sottoespressione—la sezione di inizializzazione—viene eseguita solo una volta, prima dell'esecuzione del corpo del ciclo. Perl valuta la seconda sottoespressione—il confronto condizionale—prima di ciascuna iterazione del corpo del ciclo. Quando essa ha un valore vero, l'iterazione continua. Quando ha un valore falso, l'iterazione termina. L'ultima sottoespressione viene eseguita dopo ogni iterazione del corpo del ciclo.

    for (
        # sottoespressione di inizializzazione del ciclo
        say 'Inizializzazione', my $i = 0;

        # sottoespressione di confronto condizionale
        say "Iterazione: $i" and $i < 10;

        # sottoespressione che fa terminare (prima o poi) l'iterazione
        say 'Incremento ' . $i++
    )
    {
        say "$i * $i = ", $i * $i;
    }

Notate l'assenza del punto e virgola dopo l'ultima sottoespressione, e l'uso dell'operatore virgola e dell'operatore a bassa precedenza and; questa sintassi è piuttosto complicata. Quando è possibile, preferite i cicli in stile foreach al ciclo for.

Tutte e tre le sottoespressioni sono opzionali. Un ciclo for infinito si ottiene con:

    for (;;) { ... }

While e Until

Un ciclo while continua fino a che l'espressione condizionale del ciclo assume un valore booleano falso. Un modo idiomatico di scrivere un ciclo infinito è:

    while (1) { ... }

Al contrario dell'iterazione con cicli in stile foreach, la condizione di ciclo del while non ha di per sé alcun effetto collaterale. Ovvero, se @valori contiene uno o più elementi, anche questo codice è un ciclo infinito:

    while (@valori)
    {
        say $valori[0];
    }

Per prevenire i cicli while infiniti, fate un aggiornamento distruttivo dell'array @valori modificandolo ad ogni iterazione del ciclo:

    while (@valori)
    {
        my $valore = shift @valori;
        say $valore;
    }

È anche possibile modificare @valori all'interno della condizione del while, ma ci sono alcune sottigliezze legate al valore di verità di ciascun elemento.

    while (my $valore = shift @valori)
    {
        say $valore;
    }

Questo ciclo termina non appena incontra un elemento che ha un valore falso, e quindi non esaurisce necessariamente tutto l'array. Questo potrebbe essere il comportamento desiderato, ma spesso è invece una sorpresa per i principianti.

Il ciclo until inverte il senso del test del ciclo while. L'iterazione continua finchè l'espressione condizionale del ciclo valuta a falso:

    until ($fine_corsa)
    {
        ...
    }

L'uso canonico del ciclo while è di iterare sull'input da un filehandle:

    use autodie;

    open my $fh, '<', $file;

    while (<$fh>)
    {
        ...
    }

Perl 5 interpreta questo ciclo while come se aveste scritto:

    while (defined($_ = <$fh>))
    {
        ...
    }

Senza l'uso implicito di defined, ogni linea letta dal filehandle che valuta a falso in contesto scalare—una linea vuota o una linea che contiene il solo carattere 0—farebbe terminare il ciclo. L'operatore readline (<>) restituisce un valore non definito solo quando ha raggiunto la fine del file.

chomp Sulle Vostre Linee

Usate la funzione nativa chomp per rimuovere i caratteri di fine linea da ogni linea. Molti principianti se ne dimenticano.

Sia while che until hanno forme postfisse, come il ciclo infinito 1 while 1;. Il while e l'until postfissi si possono applicare a qualunque espressione singola, incluso il classico esempio "Ciao, mondo!" dei computer a 8-bit dei primi anni '80:

    print "Ciao, mondo!  " while 1;

I cicli infiniti sono più utili di quanto potrebbero sembrare, specialmente per gli event loop nei programmi con GUI, per gli interpreti di programmi o per i server di rete:

    $server->invia_risultati() until $esegui_shutdown;

Usate un blocco do per raggruppare diverse espressioni in una singola unità:

    do
    {
        say 'Come ti chiami?';
        my $nome = <>;
        chomp $nome;
        say "Ciao, $nome!" if $nome;
    } until (eof);

Un blocco do viene interpretato come una singola espressione che può contenere diverse espressioni. Al contrario della forma a blocco del ciclo while, il blocco do con un postfisso while o until esegue il proprio corpo almeno una volta. Questo costrutto è meno comune delle altre forme di ciclo, ma non meno potente.

Cicli dentro altri Cicli

Potete annidare i cicli dentro altri cicli:

    for my $colore (@colori)
    {
        for my $valore (@valori_delle_carte) { ... }
    }

Quando lo fate, ricordatevi di dichiarare le vostre varibili di iterazione! In caso contrario, la potenziale confusione dovuta all'uso della variabile topic e al suo scope sarebbe ingestibile.

Un errore comune quando si annida un ciclo while in un ciclo foreach è che è facile esaurire un filehandle con un ciclo while:

    use autodie;

    open my $fh, '<', $un_file;

    for my $prefisso (@prefissi)
    {
        # NON USARE; probabilmente contiene un bug
        while (<$fh>)
        {
            say $prefisso, $_;
        }
    }

Aprendo il filehandle al di fuori del ciclo for, la posizione del file rimane invariata tra due iterazioni del ciclo for. Alla seconda iterazione, il ciclo while non avrà più nulla da leggere e non verrà eseguito. Per ovviare a questo problema, ri-aprite il file all'interno del ciclo for (semplice, ma non sempre ottimale per l'uso delle risorse di sistema), leggete l'intero file in memoria (potrebbe non funzionare se il file è molto grande) oppure riportate il filehandle all'inizio del file ad ogni iterazione con un seek (un'opzione spesso trascurata):

    use autodie;

    open my $fh, '<', $un_file;

    for my $prefisso (@prefissi)
    {
        while (<$fh>)
        {
            say $prefisso, $_;
        }

        seek $fh, 0, 0;
    }

Controllo di Ciclo

Talvolta, dovete uscire da un ciclo prima di avere esaurito le condizioni di iterazione. Potete usare i meccanismi standard di controllo del Perl 5—eccezioni e return—oppure le istruzioni di controllo di ciclo.

L'istruzione next fa ripartire il ciclo alla prossima iterazione. Usatelo quando avete già fatto tutto ciò che dovevate fare nell'iterazione corrente. Per scorrere le linee di un file saltando quelle che iniziano col carattere di commento #, scrivete:

    while (<$fh>)
    {
        next if /\A#/;
        ...
    }

Exit Multiple e If Annidati

Confrontate l'uso di next con l'alternativa: racchiudere il resto del corpo del blocco in un if. E ora considerate cosa succede se ci sono diverse condizioni che possono farvi saltare una linea. I modificatori di controllo di ciclo insieme ai condizionali postfissi possono rendere il vostro codice molto più leggibile.

L'istruzione last fa uscire immediatamente dal ciclo. Per finire di processare un file dopo avere incontrato un marcatore di terminazione, scrivete:

    while (<$fh>)
    {
        next if /\A#/;
        last if /\A__END__/
        ...
    }

L'istruzione redo fa ripartire l'iterazione corrente senza valutare di nuovo la condizione. Questo può essere utile in quei pochi casi in cui volete modificare subito la linea che avete letto, e quindi far ripartire l'elaborazione dalla linea modificata senza leggere un'altra linea. Un esempio un po' stupido è il seguente parser di file che unisce tra loro le linee che terminano con un backslash:

    while (my $linea = <$fh>)
    {
        chomp $linea;

        # fai il match di backslash alla fine della linea
        if ($linea =~ s{\\$}{})
        {
            $linea .= <$fh>;
            chomp $linea;
            redo;
        }

        ...
    }

Usare le istruzioni di controllo di ciclo nei cicli annidati può creare confusione. Se non potete evitare di annidare i cicli—trasformando i cicli interni in funzioni—usate una etichetta di ciclo per essere più chiari:

    LINEA:
    while (<$fh>)
    {
        chomp;

        PREFISSO:
        for my $prefisso (@prefissi)
        {
            next LINEA unless $prefisso;
            say "$prefisso: $_";
            # qui c'è un next PREFISSO implicito
        }
    }

Continue

Il costrutto continue si comporta come la terza sottoespressione di un ciclo for; Perl esegue il suo blocco prima di passare alla prossima iterazione del ciclo, sia nel caso di una ripetizione normale che nel caso di una re-iterazione prematura dovuta a next L'equivalente Perl del continue del C è next.. Potete usarlo con un ciclo while, until, when e for. Gli esempi di uso di continue sono rari, ma è utile ogni volta che volete garantire che qualcosa sia eseguito ad ogni iterazione del ciclo indipendentemente da come si conclude tale iterazione:

    while ($i < 10 )
    {
        next unless $i % 2;
        say $i;
    }
    continue
    {
        say 'Continuo...';
        $i++;
    }

Ricordate che un blocco continue not viene eseguito quando il controllo di flusso abbandona un ciclo a causa di un last o di un redo.

Given/When

Il costrutto given è una nuova funzionalità di Perl 5.10. Esso assegna il valore di un'espressione alla variabile topic ed è seguito da un blocco:

    given ($nome) { ... }

Al contrario di for, non itera su un aggregato. Valuta la propria espressione in contesto scalare, e assegna sempre alla variabile topic:

    given (my $nome_utente = trova_utente())
    {
        is( $nome_utente, $_, 'assegnamento automatico a variabile topic' );
    }

given lessicalizza la variabile topic:

    given ('topo')
    {
        say;
        da_topo_a_uomo( $_ );
        say;
    }

    sub da_topo_a_uomo { s/topo/uomo/ }

given è particolarmente utile quando è usato in combinazione con when (Matching Intelligente). given topicalizza un valore dentro un blocco in modo che diverse istruzioni when possano fare il match del topic con delle espressioni usando una semantica di smart-match. Il seguente codice implementa il gioco di Sasso, Carta e Forbici:

    my @opzioni  = ( \&sasso, \&carta, \&forbici );
    my $confuso  = "Non capisco la tua mossa.";

    do
    {
        say "Sasso, Carta e Forbici!  Scegline uno: ";
        chomp( my $mossa_utente = <STDIN> );
        my $mossa_computer = $opzioni[ rand @opzioni ];
        $mossa_computer->( lc( $mossa_utente ) );
    } until (eof);

    sub sasso
    {
        print "Ho scelto il sasso.  ";

        given (shift)
        {
            when (/carta/)    { say 'Vinci tu!' };
            when (/sasso/)    { say 'Pareggio!'  };
            when (/forbici/)  { say 'Vinco io!'   };
            default           { say $confuso  };
        }
    }

    sub carta
    {
        print "Ho scelto la carta.  ";

        given (shift)
        {
            when (/carta/)    { say 'Pareggio!'  };
            when (/sasso/)    { say 'Vinco io!'   };
            when (/forbici/)  { say 'Vinci tu!' };
            default           { say $confuso  };
        }
    }

    sub forbici
    {
        print "Ho scelto le forbici.  ";

        given (shift)
        {
            when (/carta/)    { say 'Vinco io!'   };
            when (/sasso/)    { say 'Vinci tu!' };
            when (/forbici/)  { say 'Pareggio!'  };
            default           { say $confuso  };
        }
    }

Perl esegue la regola di default quando il match con tutte le altre condizioni fallisce.

Dispatch Semplificato con i Multimetodi

Il modulo CPAN MooseX::MultiMethods fornisce un'altra tecnica per semplificare questo codice.

Chiamate di coda

Una chiamata di coda ha luogo quando l'ultima espressione in una funzione è una chiamata a un'altra funzione—il valore di ritorno della funzione chiamante è il valore di ritorno della funzione chiamata:

    sub traccia_e_saluta_persona
    {
        my $nome = shift;
        log( "Sto salutando $nome" );

        return saluta_persona( $nome );
    }

Ritornare da saluta_persona() direttamente al chiamante di traccia_e_saluta_persona() è più efficiente che ritornare a traccia_e_saluta_persona() e poi ritornare immediatamente da traccia_e_saluta_persona(). Ritornare direttamente da saluta_persona() al chiamante di traccia_e_saluta_persona() è una ottimizzazione di chiamata di coda.

Il codice fortemente ricorsivo (Ricorsione), specialmente quando ha luogo una mutua ricorsione, può consumare molta memoria. Le chiamate di coda riducono la quantità di memoria necessaria per il tracciamento interno del controllo di flusso e possono rendere trattabili degli algoritmi molto costosi. Purtroppo, Perl 5 non applica questa ottimizzazione automaticamente; dovete applicarla voi stessi quando lo ritenete necessario.

L'operatore nativo goto ha una forma per cui chiama una funzione come se la funzione corrente non fosse mai stata chiamata, cancellando in sostanza il tracciamento della chiamata alla nuova funzione. La sintassi poco elegante confonde le persone che hanno sentito dire di "Non usare mai goto", ma funziona:

    sub traccia_e_saluta_persona
    {
        my ($nome) = @_;
        log( "Sto salutando $nome" );

        goto &saluta_persona;
    }

Questo esempio mostra due aspetti importanti. Prima di tutto, goto &nome_funzione e goto &$riferimento_a_funzione richiedono di usare il sigillo di funzione (&) in modo che il parser sappia che deve effettuare una chiamata di coda anziché saltare semplicemente a un'etichetta. In secondo luogo, questa forma di chiamata di funzione passa implicitamente il contenuto di @_ alla funzione chiamata. Potete modificare @_ per cambiare gli argomenti passati.

Questa tecnica è usata piuttosto di rado; è particolarmente utile quando volete assumere voi stessi il controllo di flusso in modo da non disturbare altre funzioni che stanno ispezionando il chiamante (come quando state implementando speciali funzioni di logging o qualche sorta di funzionalità di debugging), o quando siete alle prese con un algoritmo che richiede molta ricorsione.

Scalari

Il tipo di dati fondamentale in Perl 5 è lo scalare, un valore discreto singolo. Tale valore può essere una stringa, un intero, un numero a virgola mobile, un filehandle o un riferimento—ma è sempre e comunque un singolo valore. Gli scalari possono essere variabili lessicali, di package o globali (Variabili Globali). Potete dichiarare soltanto le variabili lessicali o di package. I nomi delle variabili scalari devono conformarsi alle linee guida standard per i nomi di variabile (Nomi). Le variabili scalari usano sempre, come sigillo (Sigilli delle Variabili), il carattere del dollaro ($).

Sigilli Varianti e Contesto

I valori scalari e il contesto scalare sono fortemente legati; assegnare a uno scalare fornisce un contesto scalare. Usare il sigillo scalare con una variabile aggregato impone il contesto scalare per accedere a un singolo elemento dell'hash o dell'array.

Scalari e Tipi

Una variabile scalare può contenere qualunque tipo di valore scalare senza richiedere conversioni o cast speciali, e il tipo del valore memorizzato in una variabile può cambiare:

    my $valore;
    $valore = 123.456;
    $valore = 77;
    $valore = "Sono l'alluce di Max.";
    $valore = Negozio::Gelato->new();

Anche se questo codice è legale, cambiare il tipo di dato memorizzato in uno scalare è segno di confusione.

La flessibilità di tipo spesso causa una coercizione del valore (Coercizione). Per esempio, potreste trattare il contenuto di uno scalare come se fosse una stringa, anche se non gli avete assegnato esplicitamente una stringa:

    my $codice_postale = 10100;
    my $citta_regione_cap = 'Torino, Piemonte' . ' ' . $codice_postale;

Potete anche applicare operazioni matematiche a delle stringhe:

    my $codice_radio = 'KBMIU';

    # aggiorna codice e restituisci il nuovo valore
    my $prossimo_codice = ++$codice_radio;

    # restituisci il vecchio valore, e quindi aggiorna il codice
    my $codice_attuale = $codice_radio++;

    # così non funziona:
    my $nuovo_codice  = $codice_radio + 1;

Incremento Magico Unidirezionale

Questo incremento magico di stringa non ha un corrispondente decremento. Non potete ottenere il valore stringa precedente scrivendo $codice_radio--.

L'operazione di incremento di stringa fa diventare la a una b e la z una aa, rispettando l'insieme di caratteri e la distinzione maiuscole/minuscole. Mentre ZZ9 diventa AAA0, ZZ09 diventa ZZ10—i numeri danno luogo a riporto fino a che ci sono cifre più significative da incrementare, come sul contachilometri di un'automobile.

Valutare un riferimento (Riferimenti) in contesto stringa produce una stringa. Valutare un riferimento in contesto numerico produce un numero. Nessuna delle due operazioni modifica il riferimento, ma non potete riottenerlo dai loro risultati:

    my $autori                   = [qw( Pratchett Vinge Conway )];
    my $riferimento_come_stringa = '' . $autori;
    my $riferimento_come_numero  =  0 + $autori;

$autori è ancora un riferimento valido, ma $riferimento_come_stringa è una stringa che non ha connessioni con il riferimento e $riferimento_come_numero è un numero che non ha connessioni con il riferimento.

Per permettere di effettuare coercizioni senza perdere dei dati, gli scalari del Perl 5 possono contenere componenti sia numeriche che stringa. In Perl 5, la struttura dati interna per rappresentare uno scalare ha sia uno slot numerico che uno slot stringa. Accedere a una stringa in contesto numerico produce uno scalare con valori sia numerico che stringa. La funzione dualvar() del modulo core Scalar::Util ci permette di manipolare entrambi i valori direttamente in un singolo scalare.

Gli scalari non contengono uno slot separato per i valori booleani. In contesto booleano, la stringa vuota ('') e la stringa '0' hanno valore falso. Tutte le altre stringhe hanno valore vero. In contesto booleano, i numeri che hanno valore zero (0, 0.0, e 0e0) rappresentano il valore booleano falso. Tutti gli altri numeri rappresentano il valore vero.

Che Cos'è la Verità?

Attenzione al fatto che le stringhe '0.0' e '0e0' hanno valore vero; questo è uno dei casi in cui Perl 5 fa una distinzione fra ciò che sembra un numero e ciò che è veramente un numero.

C'è un altro valore che è sempre falso: undef. È il valore delle variabili non inizializzate ma è anche un valore di per sé.

Array

Gli array del Perl 5 sono una struttura dati di prima classe—il linguaggio li supporta come tipo di dati nativo—che memorizza zero o più scalari. Potete accedere a singoli membri dell'array con degli indici interi, e potete aggiungere o rimuovere elementi a piacere. Il sigillo @ denota un array. Per dichiarare un array, scrivete:

    my @elementi;

Elementi di un Array

Accedere a un singolo elemento di un array in Perl 5 richiede il sigillo scalare. $gatti[0] è un uso non ambiguo dell'array @gatti, dato che le parentesi quadre ([]) postfisse (Posizione) indicano sempre un accesso indicizzato a un array.

Il primo elemento di un array ha indice zero:

    # @gatti contiene una lista di oggetti Gatto
    my $primo_gatto = $gatti[0];

L'ultimo indice di un array dipende dal numero di elementi nell'array. In contesto scalare (indotto da un assegnamento scalare, una concatenzaione di stringhe, un'addizione o un contesto booleano), un array valuta al numero di elementi nell'array:

    # assegnamento scalare
    my $numero_gatti = @gatti;

    # concatenazione di stringhe
    say 'Ho ' . @gatti . ' gatti!';

    # addizione
    my $num_animali = @gatti + @cani + @pesci;

    # contesto booleano
    say 'Esatto, sono un padrone di gatti!' if @gatti;

Per ottenere l'indice dell'ultimo elemento di un array, sottraete uno dal numero di elementi dell'array (ricordate che gli indici dell'array iniziano da 0) oppure usate la meno elegante sintassi $#cats:

    my $primo_indice = 0;
    my $ultimo_indice  = @gatti - 1;
    # oppure
    # my $ultimo_indice  = $#gatti;

    say   "Il mio primo gatto ha indice $primo_indice, "
        . "e il mio ultimo gatto ha indice $ultimo_indice."

Quando l'indice è meno importante della posizione di un elemento, usate degli indici di array negativi. L'ultimo elemento di un array è accessibile all'indice -1. Il penultimo elemento dell'array è accessibile all'indice -2, e così via:

    my $ultimo_gatto    = $gatti[-1];
    my $penultimo_gatto = $gatti[-2];

$# ha un ulteriore uso: assegnandogli un valore si può ridimensionare un array. Ricordate che gli array in Perl 5 sono mutabili. Si espandono o contraggono secondo la necessità. Quando restringete un array, Perl scarterà i valori per cui non c'è posto nell'array ridimensionato. Quando espandete un array, Perl riempirà le posizioni espanse di undef.

Assegnamento ad Array

Potete fare assegnamenti a singole posizioni in un array usando gli indici:

    my @gatti;
    $gatti[3] = 'Jack';
    $gatti[2] = 'Tuxedo';
    $gatti[0] = 'Daisy';
    $gatti[1] = 'Petunia';
    $gatti[4] = 'Brad';
    $gatti[5] = 'Choco';

Se assegnate un valore a un indice oltre i limiti attuali dell'array, Perl estende l'array alla dimensione giusta e riempie tutte le posizioni intermedie con undef. Dopo il primo assegnamento nell'esempio qui sopra, l'array conterrà undef nelle posizioni 0, 1 e 2 e Jack nella posizione 3.

Come abbreviazione, potete inizializzare un array con una lista:

    my @gatti = ( 'Daisy', 'Petunia', 'Tuxedo', ... );

... ma ricordate che non sono le parentesi a creare una lista. Senza parentesi, questa istruzione assegnerebbe Daisy al primo e unico elemento dell'array, a causa delle precedenze tra operatori (Precedenza).

Un'espressione qualunque che produce una lista in contesto lista può essere assegnata ad un array:

    my @gatti      = elenca_i_gatti();
    my @info_tempo = localtime();
    my @numeri     = 1 .. 10;

Assegnare a un elemento scalare di un array impone il contesto scalare, mentre assegnare all'intero array impone il contesto lista.

Per svuotare un array, assegnategli la lista vuota:

    my @date = ( 1969, 2001, 2010, 2051, 1787 );
    ...
    @date    = ();

Gli Array all'Inizio sono Vuoti

my @elementi = (); è una versione più lunga e verbosa di my @elementi, dato che gli array appena dichiarati sono vuoti.

Operazioni sugli Array

Qualche volta è più conveniente vedere un array come una collezione ordinata e mutabile di elementi piuttosto che come una mappatura tra indici e valori. Perl 5 fornisce diverse operazioni per manipolare gli elementi di un array senza usare gli indici.

Gli operatori push e pop aggiungono e rimuovono, rispettivamente, degli elementi dalla coda di un array:

    my @piatti;

    # cosa c'è da mangiare?
    push @piatti, qw( hamburger pizza lasagne rape );

    # ... ma vostro nipote odia la verdura
    pop @piatti;

Potete fare il push di una lista di valori in un array, ma potete solo fare il pop di un elemento per volta. push restituisce il nuovo numero di elementi dell'array. pop restituisce l'elemento rimosso.

Dato che push opera su una lista, potete facilmente appendere gli elementi di uno o più array tra di loro:

    push @piatti, @colazione, @pranzo, @cena;

Analogamente, unshift e shift aggiungono e rimuovono, rispettivamente, degli elementi dalla testa di un array:

    # espandiamo i nostri orizzonti culinari
    unshift @piatti, qw( tofu spanakopita taquitos );

    # un ripensamento su quell'idea della soia
    shift @piatti;

unshift antepone una lista di elementi alla testa di un array e restituisce il nuovo numero di elementi dell'array. shift rimuove e restituisce il primo elemento dell'array.

Pochi programmi usano i valori di ritorno di push e unshift.

L'operatore splice rimuove e sostituisce elementi di un array dato un offset, la lunghezza di una slice di lista e i sostituti. Sia la sostituzione che la rimozione sono opzionali; potete omettere sia l'uno che l'altro. La descrizione di splice in perlfunc dimostra la sua equivalenza con push, pop, shift e unshift. Un uso particolarmente efficace è la rimozione di due elementi da un array:

    my ($vincitore, $secondo) = splice @finalisti, 0, 2;

    # oppure
    my $vincitore             = shift @finalisti;
    my $secondo               = shift @finalisti;

Prima del Perl 5.12, iterare su un array per indice richiedeva un ciclo in stile C. A partire da Perl 5.12, each può iterare su un array per indice e valore:

    while (my ($indice, $valore) = each @libri)
    {
        say "#$indice: $valore";
        ...
    }

Slice di Array

Il costrutto di array slice vi permette di accedere agli elementi di un array in contesto lista. A differenza dell'accesso scalare a un elemento dell'array, questa operazione di indicizzazione riceve una lista di zero o più indici e usa il sigillo array (@):

    my @gatti_giovani      = @gatti[-1, -2];
    my @gatti_anziani      = @gatti[0 .. 2];
    my @selezione_di_gatti = @gatti[ @indici ];

Le slice di array possono essere utili negli assegnamenti:

    @utenti[ @indici_sostituzioni ] = @sostituisci_utenti;

Una slice può contenere zero o più elementi—o anche uno solo:

    # slice di array con un singolo elemento; contesto lista
    @gatti[-1] = dammi_altri_gatti();

    # accesso a un singolo elemento dell'array; contesto scalare
    $gatti[-1] = dammi_altri_gatti();

L'unica differenza sintattica tra una slice di array con un solo elemento e l'accesso scalare a un elemento dell'array è il sigillo usato. La differenza semantica è maggiore: una slice di array impone sempre il contesto lista. Una slice di array valutata in contesto scalare produce un warning:

    Scalar value @gatti[1] better written as $gatti[1] at...

(NdT: tradotto sarebbe "È meglio scrivere il valore scalare @gatti[1] come $gatti[1]...").

Una slice di array impone il contesto lista anche all'espressione che usa come indice:

    # la chiamata di funzione è in contesto lista
    my @gatti_affamati = @gatti[ indici_di_gatti() ];

Array e Contesto

In contesto lista, gli array diventano liste. Se passate diversi array a una normale funzione Perl 5, essi si appiattiscono in un'unica lista:

    my @gatti = qw( Daisy Petunia Tuxedo Brad Jack );
    my @cani = qw( Rodney Lucky );

    porta_dal_veterinario( @gatti, @cani );

    sub porta_dal_veterinario
    {
        # SBAGLIATO: non usatelo!
        my (@gatti, @cani) = @_;
        ...
    }

Nella funzione, @_ conterrà sette elementi, non due, poiché l'assegnamento di una lista ad un array è greedy. Un array consuma più elementi possibile dalla lista. Dopo l'assegnamento, @gatti conterrà tutti gli argomenti passati alla funzione. @cani invece sarà vuoto.

Questo appiattimento può confondere i principianti che tentano di creare array annidati in Perl 5:

    # crea un singolo array, non un array di array
    my @numeri = (  1 .. 10,
                 ( 11 .. 20,
                 ( 21 .. 30 ) ) );

... ma questo codice è a tutti gli effetti equivalente a questo:

    # crea un singolo array, non un array di array
    my @numeri = 1 .. 30;

... perché le parentesi raggruppano semplicemente le espressioni. Non creano liste, in questo caso. Per ovviare a questo appiattimento, usate i riferimenti ad array (Riferimenti ad Array).

Interpolazione di Array

Gli array vengono interpolati in stringhe come liste della conversione in stringa di ciascun elemento separate dal valore corrente della variabile globale predefinita $". Il valore di default di tale variabile è lo spazio singolo. Il suo mnemonico in English.pm è $LIST_SEPARATOR. Quindi:

    my @alfabeto = 'a' .. 'z';
    say "[@alfabeto]";
    [a b c d e f g h i j k l m
     n o p q r s t u v w x y z]

Localizzate $" con un delimitatore per facilitare il debugging Il credito per questa tecnica va a Mark Jason Dominus.:

    # cosa c'è già in questo array?
    local $" = ')(';
    say "(@dolciumi)";
    (crostata)(torta)(ciambelle)(biscotti)(pane dolce)

Hash

Un hash è una struttura dati nativa del Perl che associa delle chiavi stringa a dei valori scalari. Allo stesso modo in cui una variabile corrisponde a un'area di memoria, una chiave di un hash si riferisce a un valore. Pensate a un hash come se fosse una guida telefonica, con cui potete usare i nomi dei vostri amici per trovare i loro numeri di telefono. In altri linguaggi gli hash sono detti tablelle, array associativi, dizionari o mappe.

Gli hash hanno due proprietà importanti: memorizzano uno scalare per ogni chiave univoca e non impongono alcun ordine specifico sulle chiavi.

Dichiarazione di Hash

Gli hash usano il sigillo %. Dichiarate un hash lessicale con:

    my %gusti_preferiti;

Un hash appena dichiarato è vuoto. Potreste anche scrivere my %gusti_preferiti = ();, ma sarebbe superfluo.

Gli hash usano il sigillo $ quando accedete a singoli elementi e le parentesi graffe { } per specificare la chiave:

    my %gusti_preferiti;
    $gusti_preferiti{Gabri} = 'Cioccolato';
    $gusti_preferiti{Anna}  = 'Vaniglia';

È possibile assegnare una lista di chiavi e valori ad un hash in un'unica espressione:

    my %gusti_preferiti = (
        'Gabri', 'Cioccolato',
        'Anna',  'Vaniglia',
    );

Se assegnate un numero dispari di elementi ad un hash, riceverete un warning. Un idioma del Perl suggerisce di usare l'operatore fat comma (=>) per associare chiavi e valori, poiché rende più esplicite tali associazioni:

    my %gusti_preferiti = (
        Gabri => 'Menta e cioccolato',
        Anna  => 'Vaniglia',
    );

L'operatore fat comma funziona come la virgola, ma quota anche la bareword (Bareword) che lo precede. La direttiva strict non genererà un warning per la presenza di tale bareword—e se avete una funzione con lo stesso nome di una chiave dell'hash, l'operatore fat comma non chiamerà la funzione:

    sub nome { 'Leonardo' }

    my %indirizzo =
    (
        nome => 'Via Fibonacci 1123',
    );

La chiave in questo hash sarà nome e non Leonardo. Se volete chiamare la funzione, dovete farlo esplicitamente:

    my %indirizzo =
    (
        nome() => 'Via Fibonacci 1123',
    );

Per svuotare un hash, assegnategli la lista vuota Potreste vedere occasionalmente anche undef %hash.:

    %gusti_preferiti = ();

Indicizzazione di Hash

Per accedere ai singoli valori di un hash dovete eseguire un'operazione di indicizzazione. Usate una chiave (operazione di accesso per chiave) per estrarre un valore da un hash:

    my $indirizzo = $indirizzi{$nome};

In questo esempio, $nome contiene una stringa che è anche una chiave dell'hash. Come per l'accesso a un singolo elemento di un array, il sigillo dell'hash è cambiato da % a $ per indicare l'accesso per chiave a un valore scalare.

Potete anche usare letterali stringa come chiavi di hash. Perl quoterà le bareword automaticamente seguendo le stesse regole del fat comma:

    # quotato automaticamente
    my $indirizzo = $indirizzi{Vittorio};

    # quotatura necessaria; non è una bareword valida
    my $indirizzo = $indirizzi{'Maria Luisa'};

    # una chiamata di funzione deve essere disambiguata
    my $indirizzo = $indirizzi{dammi_un_nome()};

Non Quotatemi

I principianti tendono a quotare i letterali stringa che usano come chiavi di hash, mentre i programmatori esperti evitano la quotatura quando è possibile. La quotatura delle chiavi di hash viene usata per segnalare l'intenzione di fare qualcos'altro.

Anche le funzioni native del Perl 5 sono soggette alla quotatura automatica:

    my %indirizzi =
    (
        Leonardo => 'Via Fibonacci 1123',
        Utako    => 'Hotel Cantor, Stanza 1',
    );

    sub da_nome_a_indirizzo
    {
        return $indirizzi{+shift};
    }

L'operatore più unario (Coercizioni Unarie) converte quella che sarebbe una bareword (shift) soggetta alla quotatura automatica in un'espressione. Da questo esempio si vede che potete usare una espressione arbitraria—non solo una chiamata di funzione—come chiave di un hash:

    # non fatelo davvero, per favore
    my $indirizzo = $indirizzi{reverse 'odranoeL'};

    # l'interpolazione funziona
    my $indirizzo = $indirizzi{"$nome $cognome"};

    # e anche le chiamate di metodi
    my $indirizzo = $indirizzi{ $utente->nome() };

Le chiavi di un hash possono solo essere stringhe. Qualunque cosa valuti ad una stringa è una chiave di hash ammissibile. Perl si spinge fino a fare la coercizione (Coercizione) di altri tipi nel tipo stringa, in modo che se usate un oggetto come chiave di hash, ottenete la versione stringa dell'oggetto anziché l'oggetto stesso:

    for my $isbn (@lista_isbn)
    {
        my $libro = Libro->per_isbn( $isbn );

        # difficile che sia quello che volevate fare
        $libri{$libro} = $libro->prezzo;
    }

Esistenza di Chiavi di Hash

L'operatore exists restituisce un valore booleano che indica se un hash contiene una data chiave:

    my %indirizzi =
    (
        Leonardo => 'Via Fibonacci 1123',
        Utako    => 'Hotel Cantor, Stanza 1',
    );

    say "Ho l'indirizzo di Leonardo"
        if exists $indirizzi{Leonardo};
    say "Ho l'indirizzo di Galileo"
        if exists $indirizzi{Galileo};

Usare exists anziché tentare di accedere direttamente a una chiave di hash evita due problemi. Prima di tutto, il controllo non viene effettuato sul valore associato alla chiave; infatti una chiave di hash potrebbe esistere e avere un valore anche se tale valore corrisponde a falso in contesto booleano (per esempio undef):

    my  %valore_chiave_falso = ( 0 => '' );
    ok( %valore_chiave_falso,
         'un hash che contiene falso sia come chiave che come valore
          dovrebbe valutare a vero' );

Inoltre, exists evita l'autovivificazione (Autovivificazione) nelle strutture dati annidate (Strutture Dati Annidate).

Se una chiave di hash esiste, il suo valore potrebbe essere undef. Potete controllarlo con defined:

    $indirizzi{Leibniz} = undef;

    say "Gottfried vive a $indirizzi{Leibniz}"
        if exists  $indirizzi{Leibniz}
        && defined $indirizzi{Leibniz};

Accedere a Chiavi e Valori degli Hash

Gli hash sono variabili aggregate, ma la loro struttura a coppie offre diverse possibilità di iterazione: sulle chiavi dell'hash, sui valori dell'hash o sulle coppie chiave/valore. L'operatore keys produce una lista di chiavi di un hash:

    for my $destinatario (keys %indirizzi)
    {
        say "Trovato l'indirizzo di $destinatario!";
    }

L'operatore values produce una lista di valori di un hash:

    for my $indirizzo (values %indirizzi)
    {
        say "Qualcuno vive in $indirizzo";
    }

L'operatore each produce una lista di liste di due elementi contenenti una chiave e il suo valore:

    while (my ($destinatario, $indirizzo) = each %indirizzi)
    {
        say "$destinatario vive in $indirizzo";
    }

Al contrario degli array, non c'è un ordinamento ovvio per queste liste. L'ordinamento dipende dall'implementazione interna dell'hash, la versione di Perl che state usando, la dimensione dell'hash e un ulteriore fattore random. Ciò nonostante, l'ordine degli elementi imposto da keys, values e each è consistente. Modificando l'hash l'ordine potrebbe cambiare, ma se l'hash rimane immutato potete fare affidamento su tale ordine.

Ogni hash ha un unico iteratore per l'operatore each. Non potete iterare su un hash con più di un each senza incorrere in problemi; se iniziate una nuova iterazione mentre un'altra è in corso, la prima terminerà prematuramente e la seconda inizierà da qualche parte in mezzo all'hash. Durante una iterazione each, fate attenzione a non chiamare funzioni che possano a loro volta tentare di iterare sull'hash con each.

In pratica questo succede raramente, ma quando vi dovesse servire resettate l'iteratore di un hash con keys o values in contesto void:

    # resetta l'iteratore dell'hash
    keys %indirizzo;

    while (my ($destinatario, $indirizzo) = each %indirizzi)
    {
        ...
    }

Slice di Hash

Una slice di hash è una lista di chiavi o valori di un hash indicizzata in una singola operazione. Per inizializzare diversi elementi di un hash in una sola istruzione:

    # %gatti contiene già altri elementi
    @gatti{qw( Jack Brad Mars Grumpy )} = (1) x 4;

Questo codice è equivalente all'inizializzazione:

    my %gatti = map { $_ => 1 }
                qw( Jack Brad Mars Grumpy );

...eccetto che l'inizializzazione di uno slice di hash non sostituisce i contenuti di un hash che esistono già.

Le slice di hash vi permettono anche di estrarre diversi valori da un hash in un'unica operazione. Come per le slice di array, il sigillo dell'hash cambia per indicare il contesto lista. L'uso delle parentesi graffe indica accesso per chiave rendendo non ambigua la presenza di un hash:

    my @indirizzi_compratori = @indirizzi{ @compratori };

Le slice di hash rendono facile anche fondere due hash insieme:

    my %indirizzi          = ( ... );
    my %indirizzi_canadesi = ( ... );

    @indirizzi{ keys   %indirizzi_canadesi }
              = values %indirizzi_canadesi;

Questo codice è equivalente a ciclare manualmente sui contenuti di %indirizzi_canadesi, ma è molto più compatto.

Che cosa succede se la stessa chiave compare in entrambi gli hash? L'uso di uno slice di hash sovrascrive sempre le coppie chiave/valore in %indirizzi. Se desiderate un comportamento diverso, è più appropriato ciclare manualmente.

L'Hash Vuoto

Un hash vuoto non contiene né chiavi né valori. In contesto booleano ha valore falso. Un hash che contiene almeno una coppia chiave/valore ha invece valore vero in contesto booleano anche se tutte le chiavi o tutti i valori o entrambi avessero valore falso in contesto booleano.

    use Test::More;

    my %vuoto;
    ok( ! %vuoto, 'un hash vuoto dovrebbe avere valore falso' );

    my %chiave_falsa = ( 0 => 'valore vero' );
    ok( %chiave_falsa, 'un hash contenente falso come chiave
                        dovrebbe avere valore vero' );

    my %valore_falso = ( 'chiave vera' => 0 );
    ok( %valore_falso, 'un hash contenente falso come valore
                        dovrebbe avere valore vero' );

    done_testing();

In contesto scalare, un hash valuta a una stringa che rappresenta la frazione di posizioni occupate nell'hash—ma potete tranquillamente ignorare questi dettagli dell'implementazione interna dell'hash.

In contesto lista, un hash valuta a una lista di coppie chiave/valore simile a quella restituita dall'operatore each. Tuttavia, non potete iterare su tale lista allo stesso modo in cui potete iterare sulla lista prodotta da each, poiché il ciclo non terminerebbe mai:

    # ciclo infinito per hash non vuoti
    while (my ($chiave, $valore) = %hash)
    {
        ...
    }

È possibile ciclare su questa lista di chiavi e valori con un ciclo for, ma la variabile iteratore conterrà una chiave ad una iterazione e il suo valore in quella successiva, poiché Perl appiattisce l'hash in un'unica lista di chiavi e valori alternati.

Idiomi degli Hash

Poiché ogni chiave può comparire una sola volta in un hash, assegnare la stessa chiave ad un hash più di una volta memorizza solo il valore più recente. Potete sfruttare questo fatto per trovare gli elementi distinti di una lista:

    my %unic;
    undef @unic{ @elementi };
    my @unici = keys %unic;

L'uso di undef con uno slice di hash setta i valori dell'hash a undef. Questo idioma rappresenta il modo più efficiente di effettuare operazioni insiemistiche con un hash.

Gli hash sono utili anche per contare degli elementi, come gli indirizzi IP in un file di log:

    my %indirizzi_ip;

    while (my $linea = <$file_di_log>)
    {
        my ($ip, $risorsa) = analizza_linea( $linea );
        $indirizzi_ip{$ip}++;
        ...
    }

Inizialmente ogni valore di un hash è undef. L'operatore di postincremento (++) lo tratta come se fosse zero. In questo esempio, se il valore della chiave esiste già viene rimpiazzato con il suo incremento. Se invece non esiste alcun valore per la chiave, Perl crea un valore (undef) e lo incrementa immediatamente a uno, dato che il valore numerico di undef è 0.

La seguente strategia costituisce un utile meccanismo di caching per memorizzare il risultato di un'operazione costosa con un piccolo overhead:

    {
        my %cache_utenti;

        sub restituisci_utente
        {
            my $id = shift;
            $cache_utenti{$id} //= crea_utente($id);
            return $cache_utenti{$id};
        }
    }

Questa manovra orchescese NdT: in inglese è un gioco di parole tra orcish (manovra da orchi) e or-cache. restituisce il valore dell'hash, se esso esiste. Altrimenti calcola, mette in cache e restituisce il valore. L'operatore di assegnamento defined-or (//=) valuta il suo operando di sinistra. Se tale operando non è definito, l'operatore gli assegna il valore del suo operando di destra. In altre parole, se non c'è un valore nell'hash per una data chiave, questa funzione chiama crea_utente() passandole la chiave e poi aggiorna l'hash.

Perl 5.10 ha introdotto gli operatori di defined-or e di assegnamento defined-or. Prima del 5.10, gran parte del codice usava l'operatore di assegnamento boolean-or (||=) per lo stesso scopo. Purtroppo, alcuni valori validi valutano a falso in contesto booleano, quindi valutare la definitezza dei valori è quasi sempre più accurato. Essendo pigra, la manovra orchescese testa la definitezza del valore in cache, non la sua verità.

Se la vostra funzione accetta diversi argomenti, sfruttate lo slurping degli argomenti (Slurping) per raccogliere delle coppie chiave/valore in un unico hash trattandole come argomenti passati per nome alla funzione:

    sub prepara_coppa
    {
        my %parametri = @_;
        ...
    }

    prepara_coppa( gusto  => 'Limone',
                   glassa => 'biscotti macinati' );

Questo approccio vi permette anche di settare dei valori di default, in questo modo:

    sub prepara_coppa
    {
        my %parametri         = @_;
        $parametri{gusto}   //= 'Vaniglia';
        $parametri{glassa}  //= 'cioccolato';
        $parametri{praline} //= 100;
        ...
    }

... oppure includendoli direttamente nell'inizializzazione dell'hash, dato che un assegnamento in una certa posizione sovrascrive gli assegnamenti che lo precedono:

    sub prepara_coppa
    {
        my %parametri =
        (
            gusto    => 'Vaniglia',
            glassa   => 'cioccolato',
            praline  => 100,
            @_,
        );
        ...
    }

Bloccare gli Hash

Dato che le chiavi di hash sono delle bareword, offrono poca protezione contro gli errori di scrittura rispetto alla protezione offerta dalla direttiva strict sui nomi di funzione e di variabile. Il poco conosciuto modulo core Hash::Util fornisce dei meccanismi per migliorare la situazione.

Per prevenire l'inserimento accidentale di una chiave di hash indesiderata (a causa di una svista o di input utente inaffidabile), usate la funzione lock_keys() per congelare l'hash al suo insieme corrente di chiavi. Ogni tentativo di aggiungere una nuova chiave all'hash solleverà un'eccezione. Questa è ovviamente una sicurezza debole, adatta solo a prevenire errori accidentali; chiunque può usare la funzione unlock_keys() per rimuovere questa protezione.

In modo simile potete bloccare o sbloccare il valore corrente di una data chiave dell'hash (lock_value() e unlock_value()) e impostare o rilasciare il modo read-only per l'intero hash con lock_hash() e unlock_hash().

Coercizione

Una variabile Perl può contenere diversi tipi di valori in momenti diversi—stringhe, interi, numeri razionali, ecc.. Anziché associare un'informazione di tipo alle variabili, Perl sfrutta il contesto fornito dagli operatori (Contesti Numerico, Stringa e Booleano) per decidere come deve interpretare i loro valori. Per scelta di progetto, Perl tenta di fare quello che intendete Abbreviato come DWIM, che sta per do what I mean (fai quello che intendo)., quindi dovete essere sufficientemente specifici sulle vostre intenzioni. Se trattate una variabile che contiene un numero come se fosse una stringa, Perl farà del suo meglio per forzare quel numero a una stringa con una coercizione.

Coercizione Booleana

La coercizione booleana ha luogo quando testate la verità di un valore, per esempio nella condizione di un if o di un while. Il numero 0, undef, la stringa vuota e la stringa '0' valutano tutti a falso. Tutti gli altri valori—incluse le stringhe che sarebbero numericamente uguali a zero come '0.0', '0e' e '0 ma vero'—valutano a vero.

Qaundo uno scalare ha sia una componente stringa che una componente numerica (Dualvar), Perl 5 preferisce testare la verità booleana della componente stringa. '0 ma vero' valuta a zero come numero, ma non è una stringa vuota, quindi in contesto booleano valuta a vero.

Coercizione a Stringa

La coercizione a stringa ha luogo quando usate degli operatori stringa come il confronto (eq e cmp), la concatenazione, split, substr e le espressioni regolari, e quando usate un valore come chiave di hash. Il valore undef diventa la stringa vuota e produce un warning di "use of uninitialized value" ("uso di valore non inizializzato"). I numeri diventano stringhe contenenti i loro valori, per esempio il valore 10 diventa la stringa '10'. Potete fare lo split di un numero in singole cifre con:

    my @cifre = split '', 1234567890;

Coercizione Numerica

La coercizione numerica ha luogo quando usate operatori di confronto numerico (come == e <=>), quando effettuate operazioni matematiche e quando usate un valore come indice di un array o di una lista. Il valore undef diventa il numero zero e produce un warning di "Use of uninitialized value". Anche le stringhe che non iniziano con una parte numerica diventano il numero zero e producono un warning di "Argument isn't numeric" ("L'argomento non è numerico"). Le stringhe che iniziano con caratteri permessi nei letterali numerici diventano dei numeri corrispondenti a tali caratteri e non producono warning; per esempio 10 salti di leptoni diventa 10 e 6.022e23 scorrerie di talpe diventa 6.022e23.

Il modulo core Scalar::Util contiene una funzione looks_like_number() che usa le stesse regole di parsing della grammatica del Perl 5 per estrarre un numero da una stringa.

Tripudio Matematico

Le stringhe Inf e Infinity rappresentano il valore infinito e si comportano come numeri. La stringa NaN rappresenta il concetto "not a number" ("non è un numero"). In contesto numerico non danno luogo al warning "Argument isn't numeric".

Coercizione di Riferimento

Usare un'operazione di dereferenziazione su un valore che non sia un riferimento trasforma quel valore in un riferimento. Questo processo di autovivificazione (Autovivificazione) è utile quando manipolate strutture dati annidate (Strutture Dati Annidate):

    my %utenti;

    $utenti{Paolo}{id} = 228;
    $utenti{Giacomo}{id} = 229;

Anche se l'hash non conteneva valori per Paolo e Giacomo, Perl si è preso il disturbo di creare dei riferimenti ad hash in queste chiavi e di assegnare una coppia chiave/valore con chiave id a ciascuno di essi.

Cache di Coercizioni

La rappresentazione interna dei valori in Perl 5 memorizza sia un valore stringa che un valore numerico. La coercizione di un valore numerico a stringa non rimpiazza il valore numerico. Invece, attacca un nuovo valore stringa, in modo che la rappresentazione contiene entrambi i componenti. Analogamente, la coercizione di una stringa a numero popola la componente numerica lasciando la componente stringa inalterata.

Certe operazioni del Perl preferiscono usare una componente di un valore piuttosto che l'altra—per esempio, i test booleani preferiscono la stringa. Se un valore si è memorizzato in cache la rappresentazione in una forma che non vi aspettate, affidarvi a una conversione implicita può dare delle sorprese. Non avrete quasi mai la necessità di esplicitare che cosa vi aspettate Il vostro autore ricorda di averlo dovuto fare solo due volte in oltre dieci anni di programmazione in Perl 5, ma sapere che questo caching ha luogo potrebbe aiutarvi una volta o l'altra a fare la diagnosi di qualche strana situazione.

Dualvar

La natura multi-componente dei valori Perl è disponibile agli utenti in forma di variabili doppie. Il modulo core Scalar::Util fornisce una funzione dualvar() che vi permette di bypassare la coercizione del Perl e manipolare separatamente le componenti stringa e numerica di un valore:

    use Scalar::Util 'dualvar';
    my $nome_falso = dualvar 0, 'Gioie & Dolori';

    say 'Vero come booleano!'  if      !! $nome_falso;
    say 'Falso come numero!'   unless  0  + $nome_falso;
    say 'Vero come stringa!'   if      ''  . $nome_falso;

Package

Un namespace in Perl associa e incapsula varie entità con nome all'interno di una categoria con un proprio nome, come potrebbe essere il vostro cognome o il nome di una marca. Al contrario di un nome nel mondo reale, un namespace non implica alcuna relazione diretta tra le entità. È possibile, ma non necessario, che vi siano tali relazioni.

In Perl 5 un package è una collezione di codice contenuto in un singolo namespace. La distinzione è sottile: il package rappresenta il codice sorgente e il namespace rappresenta l'entità creata quando Perl effettua il parsing di tale codice.

La funzione nativa package dichiara un package e un namespace:

    package MioCodice;

    our @scatole;

    sub aggiungi_scatola { ... }

Tutte le variabili e funzioni globali che dichiarate o a cui fate riferimento dopo la dichiarazione del package si riferiscono a simboli del namespace MioCodice. Potete riferirvi alla variabile @scatole dal namespace main solo col suo nome qualificato @MioCodice::scatole. Un nome qualificato include un nome completo di package, quindi potete chiamare la funzione aggiungi_scatola() soltanto con MioCodice::aggiungi_scatola().

Lo scope di un package continua fino alla successiva dichiarazione package oppure fino alle fine del file, a seconda di ciò che avviene per primo. Perl 5.14 ha potenziato package in modo che potete fornirgli un blocco che delimita esplicitamente lo scope della dichiarazione:

    package Giochi::Flipper
    {
        our $VERSION = 1969;
    }

Il package di default è il package main. In assenza di una dichiarazione di package, il package corrente è main. Questa regola si applica tanto ai programmi a linea di comando quanto ai programmi standalone e anche ai file .pm.

Oltre al nome, un package ha una versione e tre metodi impliciti: import() (Importazione), unimport() e VERSION(). VERSION() restituisce il numero di versione del package. Questo numero è in realtà una serie di numeri contenuti in una variabile globale del package di nome $VERSION. Per convenzione, le versioni tendono a essere una serie di interi separati dal punto, come 1.23 o 1.1.10, dove ogni componente è un intero.

Perl 5.12 ha introdotto una nuova sintassi intesa a semplificare i numeri di versione, come documentato in perldoc version::Internals. Questi numeri di versione con forma più restrittiva devono iniziare con il carattere v e contenere almeno tre componenti intere separate da punti:

    package MioCodice v1.2.1;

In Perl 5.14, la forma opzionale a blocco di una dichiarazione di package è:

    package Giochi::Flipper v1969.3.7
    {
        ...
    }

Nella versione 5.10 e precedenti, il modo più semplice per dichiarare la versione di un package è:

    package MioCodice;

    our $VERSION = 1.21;

Ogni package eredita un metodo VERSION() dalla classe base UNIVERSAL. Potete fare l'override di VERSION(), anche se non ci sono molti motivi per volerlo fare. Tale metodo restituisce il valore di $VERSION:

    my $versione = Qualche::Plugin->VERSION();

Se gli passate un numero di versione come argomento, il metodo solleverà un'eccezione a meno che la versione del modulo sia uguale o successiva all'argomento:

    # richiesta almeno versione 2.1
    Qualche::Plugin->VERSION( 2.1 );

    die "Il tuo plugin $version è troppo vecchio"
        unless $version > 2;

Package e Namespace

Ogni dichiarazione package crea, se necessario, un nuovo namespace e impone al parser di inserire tutti i successivi simboli globali del package (variabili globali e funzioni) in tale namespace.

Perl ha dei namespace aperti. Potete aggiungere funzioni e variabili a un namespace in qualunque punto, sia con una dichiarazione di package:

    package Pacco
    {
        sub prima_sub { ... }
    }

    Pacco::prima_sub();

    package Pacco
    {
        sub seconda_sub { ... }
    }

    Pacco::seconda_sub();

... che specificando dei nomi di funzione qualificati al momento della dichiarazione:

    # implicito
    package main;

    sub Pacco::terza_sub { ... }

Potete fare aggiunte a un package in ogni punto sia durante la compilazione che a runtime, indipendentemente dal file corrente, sebbene costruire un package con diverse dichiarazioni separate può rendere il codice difficile da esplorare.

I namespace possono avere tanti livelli quanti ne richiede il vostro schema organizzativo, ma i namespace non sono gerarchici. L'unica relazione tra i package è semantica, non tecnica. Molti progetti e aziende creano il proprio namespace di top-level. In questo modo viene ridotta la possibilità di conflitti globali e viene semplificata l'organizzazione del codice su disco. Per esempio:

... e così via.

Riferimenti

Normalmente Perl fa ciò che vi aspettate, anche quando ci sono delle sottigliezze. Considerate ciò che accade quando passate dei valori a una funzione:

    sub saluto_rovesciato
    {
        my $nome = reverse shift;
        return "Ciao, $nome!";
    }

    my $nome = 'Max';
    say saluto_rovesciato( $nome );
    say $nome;

Al di fuori della funzione, $nome contiene Max, anche se il valore passato alla funzione viene invertito in xaM. Probabilmente è quello che vi aspettavate. Il valore di $nome al di fuori della funzione è separato dal $nome dentro alla funzione. Modificarne uno non ha effetti sull'altro.

Considerate l'alternativa. Se doveste fare delle copie di ogni valore prima che qualcosa possa cambiarli senza il vostro consenso, dovreste scrivere un sacco di codice extra.

Tuttavia alcune volte è utile che i valori possano essere modificati. Se volete passare a una funzione un hash pieno di dati perché vengano modificati, creare e restituire un nuovo hash per ogni modifica è scomodo (per non dire nulla dell'efficienza).

Perl 5 fornisce un meccanismo con cui potete riferirvi a un valore senza farne una copia. Ogni modifica fatta a quel riferimento ne aggiorna il valore in un modo visibile a tutti i riferimenti che lo possono raggiungere. Un riferimento è un tipo di dato scalare di prima classe di Perl 5 che si riferisce ad un altro tipo di dato di prima classe.

Riferimenti a Scalari

L'operatore di riferimento è il backslash (\). In contesto scalare, crea un singolo riferimento ad un altro valore. In contesto lista, crea una lista di riferimenti. Per ottenere un riferimento a $nome:

    my $nome       = 'Larry';
    my $rif_a_nome = \$nome;

Dovete dereferenziare un riferimento per accedere al valore cui si riferisce. La dereferenziazione vi richiede di aggiungere un sigillo extra per ogni livello di indirezione:

    sub inverti_sul_posto
    {
        my $rif_a_nome = shift;
        $$rif_a_nome   = reverse $$rif_a_nome;
    }

    my $nome = 'Chiacchierone';
    reverse_in_place( \$nome );
    say $nome;

Il sigillo scalare doppio ($$) dereferenzia un riferimento a scalare.

Nell'array @_, i parametri si comportano come alias alle variabili del chiamante Ricordate che i cicli for producono un comportamento simile., quindi potete modificarli:

    sub inverti_sul_posto
    {
        $_[0] = reverse $_[0];
    }

    my $nome = 'ollirdoccoC';
    inverti_sul_posto( $name );
    say $name;

Normalmente, non desiderate modificare dei valori in questo modo—e i chiamanti raramente se lo aspettano. Assegnare i parametri a dei lessicali nelle vostre funzioni evita questo rischio.

Risparmiare Memoria con i Riferimenti

Modificare direttamente un valore o restituire un riferimento a uno scalare può farvi risparmiare memoria. Dato che gli assegnamenti in Perl copiano i valori, potreste ritrovarvi con diverse copie di una stringa molto lunga. Passare dei riferimenti implica che il Perl deve solo copiare tali riferimenti—un'operazione molto meno dispendiosa.

Riferimenti complessi possono richiedere un blocco tra parentesi graffe per disambiguare parti dell'espressione. Potete sempre usare questa sintassi, anche se non sempre rende il codice più chiaro:

    sub inverti_sul_posto
    {
        my $rif_a_nome   = shift;
        ${ $rif_a_nome } = reverse ${ $rif_a_nome };
    }

Se vi dimenticate di dereferenziare un riferimento a scalare, probabilmente Perl applicherà una coercizione al riferimento. Il valore stringa sarà nella forma SCALAR(0x93339e8) e il valore numerico sarà la porzione 0x93339e8. Questo valore codifica il tipo di riferimento (in questo caso, SCALAR) e la locazione di memoria del riferimento.

I Riferimenti Non Sono Puntatori

Perl non offre nativamente accesso alle locazioni di memoria. L'indirizzo di un riferimento è un valore usato come identificatore. Diversamente dai puntatori in un linguaggio come il C, non potete modificare questo indirizzo o comunque trattarlo come un indirizzo in memoria. Questi indirizzi sono solo quasi univoci dato che il Perl potrebbe riutilizzare le stesse locazioni di memoria dopo avere reclamato della memoria inutilizzata.

Riferimenti ad Array

I riferimenti ad array sono utili in diverse circostanze:

Usate l'operatore di riferimento per creare un riferimento ad un array dichiarato in precedenza:

    my @carte       = qw( K Q J 10 9 8 7 6 5 4 3 2 A );
    my $rif_a_carte = \@carte;

Ogni modifica fatta attraverso $rif_a_carte modificherà @carte e viceversa. Potete accedere all'intero array con il sigillo @, sia per appiattirlo in una lista che per contarne gli elementi:

    my $conteggio_carte = @$rif_a_carte;
    my @copia_carte     = @$rif_a_carte;

Accedete a singoli elementi dell'array usando una freccia di dereferenziazione (->):

    my $prima_carta  = $rif_a_carte->[0];
    my $ultima_carta = $rif_a_carte->[-1];

La freccia è necessaria per distinguere tra uno scalare di nome $rif_a_carte e un array di nome @rif_a_carte. Notate l'uso del sigillo scalare (Sigilli delle Variabili) per accedere a un singolo elemento.

Raddoppiare i Sigilli

Una sintassi alternativa antepone il sigillo scalare al riferimento ad array. Anche se meno elegante, my $prima_carta = $$rif_a_carte[0]; è più breve da scrivere.

Usate le parentesi graffe per dereferenziare una slice (Slice di Array) di un riferimento ad array:

    my @carte_alte = @{ $rif_a_carte }[0 .. 2, -1];

È possibile omettere le parentesi graffe, ma usarle come raggruppamenti spesso migliora la leggibilità.

Per creare un array anonimo—che non è stato dichiarato—racchiudete una lista di valori tra parentesi quadre:

    my $rif_a_cose_varie = [qw( Scimmie Robot Dinosauri Formaggi )];

Questo riferimento ad array è identico a un riferimento a un array con nome, eccetto che le parentesi quadre dell'array anonimo creano sempre un nuovo riferimento. Se chiedete diversi riferimenti ad un array con nome essi si riferiscono sempre allo stesso array all'interno di uno stesso scope. Per esempio, se scrivete:

    my @piatti           = qw( zuppa panini pizza );
    my $rif_per_domenica = \@piatti;
    my $rif_per_lunedi   = \@piatti;

    push @piatti, 'coppa di gelato';

...alla fine sia $rif_per_domenica che $rif_per_lunedi conterranno un dessert, mentre se scrivete:

    my @piatti           = qw( zuppa panini pizza );
    my $rif_per_domenica = [ @piatti ];
    my $rif_per_lunedi   = [ @piatti ];

    push @piatti, 'crostata di mirtilli';

...né $rif_per_domenica$rif_per_lunedì conterranno un dessert. All'interno delle parentesi quadre usate per creare l'array anonimo, il contesto lista appiattisce l'array @piatti in una lista separata da @piatti.

Riferimenti a Hash

Usate l'operatore di riferimento su un hash per creare un riferimento a hash:

    my %colori = (
        nero    => 'negro',
        blu     => 'azul',
        oro     => 'dorado',
        rosso   => 'rojo',
        giallo  => 'amarillo',
        porpora => 'morado',
    );

    my $rif_a_colori = \%colori;

Per accedere alle chiavi o ai valori dell'hash anteponete il sigillo di hash % al riferimento:

    my @colori_italiani = keys   %$rif_a_colori;
    my @colori_spagnoli = values %$rif_a_colori;

Per accedere a singoli valori dell'hash (ovvero modificarli, cancellarli, controllarne l'esistenza ed estrarli) usate la freccia di dereferenziazione o un sigillo doppio:

    sub traduci_in_spagnolo
    {
        my $colore = shift;
        return $rif_a_colori->{$colore};
        # oppure return $$rif_a_colori{$colore};
    }

Per le slice di riferimenti ad hash usate il sigillo array (@) e le parentesi graffe per disambiguare:

    my @colori  = qw( rosso blu verde );
    my @colores = @{ $rif_a_colori }{@colori};

Per creare hash anonimi usate le parentesi graffe:

    my $rif_a_cibo = {
        'torta di compleanno' => 'la torta de cumpleaños',
        dolci                 => 'dulces',
        biscotto              => 'bizcochito',
        gelato                => 'helado',
    };

Come per gli array anonimi, ogni volta vengono creati dei nuovi hash anonimi.

Attenzione alle Graffe!

Un errore comune per i principianti è quello di assegnare un hash anonimo ad un hash standard, il che produce un warning relativo ad un numero dispari di elementi nell'hash. Usate le parentesi tonde per assegnare a un hash standard e le parentesi graffe per creare un hash anonimo.

Dereferenziazione Automatica

A partire dalla versione 5.14, il Perl può dereferenziare automaticamente alcuni riferimenti al posto vostro. Dato un riferimento ad array in $rif_a_array, potete scrivere:

    push $rif_a_array, qw( lista di valori );

Potete fare la stessa cosa con un'espressione che restituisce un riferimento ad array:

    push $case{$luogo}[$armadi], \@scarpe_nuove;

Lo stesso vale per gli operatori su array pop, shift, unshift, splice, keys, values e each e gli operatori su hash keys, values e each.

Se il riferimento usato non è del tipo opportuno—ovvero se non può essere dereferenziato correttamente—Perl solleverà un'eccezione. Questo potrebbe sembrare più pericoloso di dereferenziare esplicitamente i riferimenti, ma è invece la stessa cosa:

    my $rif = sub { ... };

    # lancia un'eccezione
    push  $rif, qw( lista di valori );

    # anche questo lancia un'eccezione
    push @$rif, qw( lista di valori );

Riferimenti a Funzioni

Perl 5 supporta le funzioni di prima classe, ovvero la funzione è un tipo di dati esattamente come lo sono l'array e l'hash. Questo fatto è reso particolarmente evidente dai riferimenti a funzione, e rende possibili molte funzionalità avanzate (Chiusure). Per creare un riferimento a funzione usate l'operatore di riferimento sul nome della funzione:

    sub cuoci_torta { say 'Sto cuocendo un\'ottima torta!' };

    my $rif_a_torta = \&cuoci_torta;

Se non usate il sigillo funzione (&), otterrete un riferimento al valore o ai valori di ritorno della funzione.

Per creare delle funzioni anonime usate la keyword sub senza nome:

    my $rif_a_dolce = sub { say 'Sto facendo una torta deliziosa!' };

L'uso di sub senza un nome compila la funzione normalmente, ma non la installa nel namespace corrente. L'unico modo per accedere a tale funzione è attraverso il riferimento restituito da sub. Invocate il riferimento a funzione con la freccia di dereferenziazione:

    $rif_a_torta->();
    $rif_a_dolce->();

Chiamate di Funzione in Perl 4

Un modo alternativo per invocare riferimenti a funzione è quello di usare il sigillo funzione (&) invece della freccia di dereferenziazione. Evitate questa sintassi, dato che ha alcune insidiose implicazioni per il parsing e per il passaggio degli argomenti.

Pensate alle parentesi vuote come a un'operazione che indica la dereferenziazione di un'invocazione così come le parentesi quadre indicano un accesso per indice ad un array e le parentesi graffe indicano un accesso a un hash. Passate gli argomenti alla funzione dentro le parentesi:

    $rif_a_cuoci_qualcosa->( 'biscotti' );

Potete anche usare i riferimenti a funzione come metodi di oggetti (Moose). Questo può essere utile quando avete dovuto fare una ricerca del metodo stesso (Riflessione):

    my $pulisci = $colf_robotica->can( 'pulisci' );
    $colf_robotica->$pulisci( $cucina );

Riferimenti a Filehandle

Quando usate la forma di open (e opendir) con filehandle lessicale, vi trovate ad avere a che fare con riferimenti a filehandle. Internamente, questi filehandle sono oggetti IO::File. Potete chiamare direttamente dei metodi su di essi. A partire da Perl 5.14, potete farlo semplicemente scrivendo:

    open my $out_fh, '>', 'file_di_output.txt';
    $out_fh->say( 'Ecco un po\' di testo!' );

Per attivare questa funzionalità, in Perl 5.12 dovete fare la use IO::File; in Perl 5.10 e versioni precedenti dovete fare la use IO::Handle;. Anche il codice meno recente può creare dei riferimenti a typeglob:

    local *FH;
    open FH, "> $file" or die "Non posso scrivere su '$file': $!";
    my $fh = \*FH;

Questo idioma è antecedente alla comparsa dei filehandle lessicali (avvenuta con Perl 5.6.0 nel Marzo del 2000). Potete ancora usare l'operatore di riferimento a typeglob per ottenere riferimenti ai filehandle globali del package come STDIN, STDOUT, STDERR e DATA—ma questi nomi sono comunque globali.

Dovunque è possibile, è preferibile usare i filehandle lessicali. Con tutti i benefici di uno scope esplicito, i filehandle lessicali vi permettono di gestire la durata della vita di un filehandle tramite le funzionalità di gestione dello scope di Perl 5.

Reference Count

Perl 5 usa una tecnica di gestione della memoria nota come reference counting. Ogni valore Perl ha un contatore associato. Perl incrementa tale contatore ogni volta che viene richiesto un riferimento al valore, sia implicito che esplicito. Analogamente, Perl decrementa tale contatore ogni volta che un riferimento scompare. Quando il contatore arriva a zero, Perl può riciclare il valore in modo sicuro.

Come fa il Perl a sapere quando può rilasciare la memoria associata a una variabile senza causare problemi? Come fa il Perl a sapere quando è sicuro chiudere il file aperto nello scope più interno del seguente codice?

    say 'file non aperto';

    {
        open my $fh, '>', 'scope_interno.txt';
        $fh->say( 'qui il file e` aperto' );
    }

    say 'qui il file e` chiuso';

Nel blocco interno dell'esempio, c'è un unico $fh (diverse linee del codice sorgente si riferiscono ad esso, usando però sempre la stessa variabile: $fh). Lo scope di $fh è il blocco interno. Il suo valore non può superare i limiti di tale blocco. Perciò, quando l'esecuzione raggiunge la fine del blocco, Perl ricicla la variabile $fh e decrementa il reference count del filehandle che essa contiene. Il reference count del filehandle arriva a zero e Perl può riciclarlo reclamandone la memoria associata e chiamando close() implicitamente.

Non è necessario che comprendiate tutti i dettagli di questo meccanismo. Dovete però capire che le vostre azioni di creazione di riferimenti e passaggio degli stessi ad altre parti del codice hanno un impatto sulla gestione della memoria del Perl (vedete Riferimenti Circolari).

Riferimenti e Funzioni

Quando usate dei riferimenti come argomenti di funzioni, documentate attentamente le vostre intenzioni. Modificare i valori di un riferimento all'interno di una funzione potrebbe sorprendere il codice chiamante, se esso si aspetta che nessun altro modifichi i suoi dati. Per modificare il contenuto di un riferimento senza effetti per il riferimento stesso, copiate i suoi valori in una nuova variabile:

    my @nuovo_array = @{ $array_ref };
    my %nuovo_hash  = %{ $hash_ref  };

Fare questo è necessario solo in qualche caso, ma la duplicazione esplicita aiuta ad evitare spiacevoli sorprese per il chiamante. Se usate strutture dati annidate o altri riferimenti complessi, considerate l'uso del modulo core Storable e la sua funzione dclone (deep cloning).

Strutture Dati Annidate

I dati aggregati del Perl—array e hash—vi permettono di memorizzare scalari e indicizzarli per numero o per chiave. I riferimenti Perl 5 (Riferimenti) vi permettono di accedere ai tipi di dati aggregati attraverso speciali variabili scalari. Le strutture dati annidate del Perl, come un array di array o un hash di hash, sono rese possibili dall'uso dei riferimenti.

Per dichiarare una struttura dati annidata, usate la sintassi della dichiarazione di riferimenti anonimi:

    my @terzetti_famosi = (
        [qw( emy ely evy   )],
        [qw( qui quo qua )],
        [qw( aldo giovanni giacomo )],
    );

    my %pasti = (
        colazione => { piatto   => 'uova',
                       contorno => 'patatine' },
        pranzo    => { piatto   => 'panini',
                       contorno => 'mela'     },
        cena      => { piatto   => 'bistecca',
                       contorno => 'insalata di avocado' },
    );

Le Virgole sono Gratuite

Perl permette, ma non richiede, la virgola finale come modo per facilitare l'aggiunta di nuovi elementi alla lista.

Usate la sintassi dei riferimenti Perl per accedere agli elementi delle strutture dati annidate. Il sigillo denota la quntità di dati da estrarre e la freccia di dereferenziazione indica che il valore di una porzione della struttura dati è un riferimento:

    my $ultimo_nipote        = $terzetti_famosi[1]->[2];
    my $parte_del_risveglio  = $pasti{colazione}->{contorno};

L'unico modo di annidare una struttura dati multi-livello è attraverso i riferimenti, quindi la freccia è superflua. Potete ometterla per chiarezza, eccetto quando invocate un riferimento a funzione:

    my $nipote = $terzetti_famosi[1][2];
    my $pasto  = $piatti{colezione}{contorno};
    $azioni{finanziarie}{compra_cibo}->( $nipote, $pasto );

Usate dei blocchi di disambiguazione per accedere ai componenti delle strutture dati annidate come se fossero array o hash di prima classe:

    my $conteggio_nipoti = @{ $terzetti_famosi[1] };
    my $per_la_cena      = keys %{ $piatti{cena} };

... o per le slice di strutture dati annidate:

    my ($piatto, $contorno) = @{ $piatti{colazione} }
                               {qw( piatto contorno )};

La spaziatura può aiutare, ma non elimina completamente la difficoltà di leggere questo costrutto. Per essere più chiari, usate delle variabili temporanee:

    my $rif_a_pasto         = $piatti{colazione};
    my ($piatto, $contorno) = @$rif_a_pasto{qw( piatto contorno )};

... oppure sfruttare l'aliasing implicito a $_ del ciclo for per evitare l'uso di un riferimento intermedio:

    my ($piatto, $contorno) = @{ $_ }{qw( piatto contorno )}
                              for $pasti{colazione};

perldoc perldsc, il ricettario sulle strutture dati, fornisce numerosi esempi di uso di varie strutture dati in Perl.

Autovivificazione

Quando tentate di scrivere dentro un componente di una struttura dati annidata, Perl creerà il cammino necessario nella struttura dati fino alla destinazione:

    my @adadada;
    $adadada[0][0][0][0] = 'profondamente annidato';

Dopo la seconda linea di codice, questo array di array di array di array contiene un riferimento ad array in un riferimento ad array in un riferimento ad array in un riferimento ad array. Ogni riferimento ad array contiene un elemento. Analogamente, se trattate un valore non definito come se fosse un riferimento ad hash in una struttura dati annidata, Perl lo inizializzerà di conseguenza:

    my %hdh;
    $hdh{Computer}{Disco} = 'molto pericoloso';

Questo utile processo è detto autovivificazione. Anche se riduce il codice di inizializzazione delle strutture dati annidate, non distingue tra un vero intento di creare elementi mancanti e gli errori di battitura. La direttiva autovivification di CPAN (Direttive) vi permette di disabilitare l'autovivificazione in uno scope lessicale per specifici tipi di operazioni.

Potreste vedere una contraddizione nell'idea di sfruttare l'autovivificazione attivando al contempo controlli come strict. È un problema di bilanciamento. È più conveniente catturare gli errori che fanno cambiare il comportamento del vostro programma al costo di disabilitare i controlli su alcuni riferimenti simbolici ben identificati? È più conveniente permettere alle strutture dati di crescere piuttosto che dover specificare la loro dimensione e le chiavi permesse?

Le risposte dipendono dal vostro progetto. All'inizio dello sviluppo, concedetevi la libertà di sperimentare. Quando arrivate al test e alla distribuzione, considerate di incrementare le restrizioni per evitare effetti collaterali indesiderati. Grazie allo scope lessicale delle direttive strict e autovivification, potete abilitarle dove e quando lo ritenete necessario.

Naturalmente potreste verificare le vostre aspettative prima di dereferenziare ogni livello di una struttura dati complessa, ma il codice risultante sarebbe lungo e tedioso. La cosa migliore è di evitare strutture dati annidate troppo profondamente rivedendo il vostro modello dei dati e migliorarne l'incapsulamento.

Debugging di Strutture Dati Annidate

La complessità della sintassi di dereferenziazione di Perl 5 combinata con la potenziale confusione dovuta a molti livelli di indirezione possono rendere difficile il debugging delle strutture dati annidate. Fortunatamente esistono due validi strumenti di visualizzazione.

Il modulo core Data::Dumper converte valori di complessità arbitraria in stringhe di codice Perl 5:

    use Data::Dumper;

    print Dumper( $struttura_complessa );

Può essere utile per vedere che cosa contiene una struttura dati, a che cosa volevate accedere e a che cosa avete invece acceduto. Data::Dumper può fare il dump di oggetti e anche di riferimenti a funzione (se settate $Data::Dumper::Deparse al valore vero).

Anche se Data::Dumper è un modulo core e stampa codice Perl 5, il suo output è verboso. Alcuni sviluppatori preferiscono usare i moduli YAML::XS o JSON per il debugging. Questi moduli non producono codice Perl 5, ma i loro output possono essere molto più chiari da leggere e capire.

Riferimenti Circolari

Il sistema di gestione della memoria di Perl 5 ha un problema con il reference counting (Reference Count) che diventa visibile al livello del codice utente. Due riferimenti che finiscono indirettamente per puntare l'uno all'altro formano un riferimento circolare che Perl non può neutralizzare automaticamente. Considerate un modello biologico, dove ogni entità ha due genitori e zero o più figli:

    my $alice   = { madre => '',     padre => ''      };
    my $roberto = { madre => '',     padre => ''      };
    my $carla   = { madre => $alice, padre => $roberto };

    push @{ $alice->{figli}  }, $carla;
    push @{ $roberto->{figli} }, $carla;

Sia $alice che $roberto contengono un riferimento ad array che contiene $carla. Dato che $carla è un riferimento a un hash che contiene sia $alice che $roberto, Perl non decrementerà mai il reference count di queste tre persone a zero. Non riconosce l'esistenza di questi riferimenti circolari e non può gestire la durata della vita di queste entità.

Potete spezzare il circolo manualmente (resettando i figli di $alice e $roberto o i genitori di $carla), oppure usare i riferimenti deboli. Un riferimento debole è un riferimento che non incrementa il reference count del suo referente. I riferimenti deboli sono resi disponibili dal modulo core Scalar::Util. La funzione weaken() previene l'incremento di un reference count:

    use Scalar::Util 'weaken';

    my $alice   = { madre => '',     padre => ''      };
    my $roberto = { madre => '',     padre => ''      };
    my $carla   = { madre => $alice, padre => $roberto };

    push @{ $alice->{figli}  }, $carla;
    push @{ $roberto->{figli} }, $carla;

    weaken( $carla->{madre} );
    weaken( $carla->{padre} );

In questo modo $carla mantiene i suoi riferimenti ad $alice e $roberto, ma tali riferimenti non prevengono il garbage collector del Perl dal distruggere le relative strutture dati. Molte strutture dati non necessitano dei riferimenti deboli, ma quando sono necessari hanno un valore inestimabile.

Alternative alle Strutture Dati Annidate

Anche se il Perl è ben contento di processare strutture dati annidate a qualunque profondità possiate immaginare, il costo di comprendere queste strutture dati e le loro relazioni per un lettore umano è alto—per non dire nulla della complessità della sintassi. Oltre i due o tre livelli di annidamento, considerate se modellare i diversi componenti del vostro sistema con classi e oggetti (Moose) non potrebbe rendere più chiaro il vostro codice.