Operatori

Alcune persone definiscono il Perl come un "linguaggio orientato agli operatori". Per riuscire a capire un programma Perl, dovete sapere come i suoi operatori interagiscono con i propri operandi.

Un operatore Perl è una sequenza di uno o più simboli usati come parte della sintassi di un linguaggio. Ogni operatore opera su zero o più operandi. Pensate ad un operatore come a uno speciale tipo di funzione che il parser riconosce e ai suoi operandi come ad argomenti.

Caratteristiche degli Operatori

Ogni operatore ha molte importanti caratteristiche che ne determinano il comportamento: il numero di operandi su cui opera, le sue relazioni con altri operatori e le sue possibilità sintattiche.

perldoc perlop e perldoc perlsyn contengono molte informazioni sugli operatori Perl, ma la documentazione assume che abbiate già familiarità con alcuni dettagli sul loro funzionamento. I concetti di informatica di base richiesti possono forse sembrare altisonanti a prima vista, ma se andate al di là dei loro nomi risultano semplici. E anche se non li avete mai usati esplicitamente, ne conoscete già il significato.

Precedenza

La precedenza di un operatore determina quando esso viene valutato da Perl in una espressione. L'ordine di valutazione va dalla precedenza più alta a quella più bassa. Poiché la precedenza della moltiplicazione è più alta della precedenza dell'addizione, 7 + 7 * 10 valuta a 77 e non 140.

Per forzare la valutazione di un operatore prima di un altro, raggruppate le sue sottoespressioni tra parentesi. Se scrivete (7 + 7) * 10, raggruppando l'addizione in una singola unità forzate la sua valutazione prima della moltiplicazione. Il risultato diventa 140.

perldoc perlop contiene una tabella delle precedenze. Leggetela, cercate di capirne il contenuto, ma non preoccupatevi di impararla a memoria (quasi nessuno lo fa). Impegnatevi piuttosto a mantenere semplici le vostre espressioni e aggiungete delle parentesi per chiarire le vostre intenzioni.

Quando due operatori hanno la stessa precedenza, altri fattori quali l'associatività (Associatività) e la posizione (Posizione) aiutano a eliminare l'ambiguità.

Associatività

L'associatività di un operatore determina se esso valuta da sinistra verso destra o da destra verso sinistra. L'addizione è associativa a sinistra, quindi 2 + 3 + 4 valuta prima 2 + 3 e poi aggiunge 4 al risultato. L'elevamento a potenza è associativo a destra, quindi 2 ** 3 ** 4 valuta prima 3 ** 4 e poi eleva 2 all'81esima potenza.

Può valere la pena memorizzare la precedenza e l'associatività degli operatori matematici più comuni, ma come detto sopra la regola aurea è comunque la semplicità. Usate le parentesi per rendere chiare le vostre intenzioni.

Arità

L'arità di un operatore è il numero di operandi su cui opera. Un operatore nullario opera su zero operandi. Un operatore unario opera su un operando. Un operatore binario opera su due operandi. Un operatore ternario opera su tre operandi. Un operatore poliadico opera su una lista di operandi. La documentazione di un operatore e i relativi esempi dovrebbero chiarire qual è la sua arità.

Per esempio, gli operatori aritmetici sono operatori binari e di solito sono associativi a sinistra. 2 + 3 - 4 valuta prima 2 + 3; infatti l'addizione e la sottrazione hanno la stessa precedenza, ma essendo binari e associativi a sinistra un corretto ordine di valutazione applica l'operatore più a sinistra (+) ai due operandi più a sinistra (2 e 3) e quindi applica l'operatore più a destra (-) al risultato della prima operazione e all'operando più a destra (4).

I principianti Perl sono spesso confusi dall'interazione tra gli operatori poliadici—specialmente le chiamate di funzione—e le espressioni annidate. Se è vero che spesso le parentesi aiutano, attenzione alle complicazioni del parsing di:

    # probabilmente codice bacato
    say ( 1 + 2 + 3 ) * 4;

... che stampa il valore 6 e (probabilmente) valuta complessivamente a 4 (il valore di ritorno di say moltiplicato per 4). Il parser di Perl interpreta tranquillamente le parentesi come un operatore di post-raggruppamento (Posizione) che denota gli argomenti di say, non come un operatore di raggruppamento di un'espressione usato per cambiare le precedenze.

Posizione

La posizione di un operatore determina il suo posizionamento rispetto ai suoi operandi:

Tipi di Operatori

Gli operatori del Perl forniscono contesti di valore (Contesti Numerico, Stringa e Booleano) ai propri operandi. Per scegliere l'operatore appropriato, dovete tenere conto dei valori degli operandi che gli passate e del valore che vi aspettate di ricevere.

Operatori Numerici

Gli operatori numerici impongono il contesto numerico ai loro operandi. Questi operatori sono: gli operatori aritmetici standard come addizione (+), sottrazione (-), moltiplicazione (*), divisione (/), elevamento a potenza (**) e modulo (%); le loro varianti di assegnamento composto (+=, -=, *=, /=, **= e %=); e l'auto-decremento (--) sia postfisso che prefisso.

L'operatore di auto-incremento ha uno speciale comportamento in contesto stringa (Operatori Speciali).

Diversi operatori di confronto impongono il contesto numerico ai loro operandi. Questi operatori sono: uguaglianza numerica (==), disuguaglianza numerica (!=), maggiore di (>), minore di (<), maggiore o uguale (>=), minore o uguale (<=) e l'operatore di confronto per il sort (<=>).

Operatori Stringa

Gli operatori stringa impongono il contesto stringa ai loro operandi. Questi operatori sono il binding positivo e negativo a un'espressione regolare (=~ e !~, rispettivamente) e la concatenazione (.).

Diversi operatori di confronto impongono il contesto stringa ai loro operandi. Questi operatori sono: uguaglianza di stringhe (eq), disuguaglianza di stringhe (ne), maggiore di (gt), minore di (lt), maggiore o uguale (ge), minore o uguale (le) e l'operatore di confronto tra stringhe per il sort (cmp).

Operatori Logici

Gli operatori logici impngono il contesto booleano ai loro operandi. Questi operatori sono &&, and, || e or. Sono tutti infissi e tutti possono dar luogo a cortocircuiti (Cortocircuiti). Le varianti and e or hanno precedenza più bassa delle corrispondenti forme simboliche.

L'operatore defined-or, //, controlla se il proprio operando è definito. Contrariamente a || che testa la verità del proprio operando, // valuta a vero anche se il suo operando valuta al numero zero o alla stringa vuota. Questo risulta particolarmente utile per impostare i valori di default dei parametri:

    sub chiama_il_cane
    {
        my $nome = shift // 'Fuffy';
        ...
    }

L'operatore condizionale ternario (?:) riceve tre operandi. Valuta il primo in contesto booleano e continua con la valutazione del secondo se il primo è vero e del terzo in caso contrario:

    my $verità = $valore ? 'vero' : 'falso';

Gli operatori prefissi ! e not restituiscono l'opposto del valore booleano dei loro operandi. not è la versione di ! con precedenza più bassa.

L'operatore xor è un operatore infisso che valuta all' or-esclusivo dei suoi operandi.

Operatori bit-a-bit

Gli operatori bit-a-bit trattano a livello di bit i numeri rappresentati dai propri operandi. Queste operazioni, piuttosto rare, sono: shift a sinistra (<<), shift a destra (>>), and bit-a-bit (&), or bit-a-bit (|) e xor bit-a-bit (^); e le loro varianti di assegnamento composto (<<=, >>=, &=, |= e ^=).

Operatori Speciali

L'operatore di auto-incremento ha un comportamento speciale. Quando è usato su un valore che ha una componente numerica (Cache di Coercizioni), l'operatore incrementa tale componente numerica. Se invece il valore è solamente una stringa (e non ha una componente numerica), l'operatore incrementa tale valore stringa in modo che a diventa b, zz diventa aaa e a9 diventa b0.

    my $num = 1;
    my $str = 'a';

    $num++;
    $str++;
    is( $num,   2, 'autoincremento numerico' );
    is( $str, 'b', 'autoincremento stringa'  );

    no warnings 'numeric';
    $num += $str;
    $str++;

    is( $num, 2, 'un'addizione numerica con $str'    );
    is( $str, 1, '...genera una componente numerica per $str' );

L'operatore di ripetizione (x) è un operatore infisso con un comportamento complesso. In contesto lista, se riceve una lista valuta a quella lista ripetuta un numero di volte pari al suo secondo operando. In contesto lista, se riceve uno scalare produce una stringa che consiste nel valore stringa del suo primo operando concatenata con se stessa un numero di volte pari al suo secondo operando.

In contesto scalare, l'operatore produce sempre una stringa ottenuta con il numero appropriato di concatenazioni. Per esempio:

    my @sherazad   = ('notti') x 1001;
    my $calendario =  'notti'  x 1001;
    my $lung_cal   =  length $calendario;

    is( @sherazad,   1001, 'lista ripetuta' );
    is( $lung_cal,   1001 * length 'notti',
                     'parola ripetuta' );

    my @shestringa =  'notti'  x 1001;
    my $calscalare = ('notti') x 1001;

    is( @shestringa, 1, 'contiene una sola stringa' );
    is( length $calscalare,
        1001 * length 'notti', 'sempre parola ripetuta' );

L'operatore infisso di intervallo (..) produce una lista di elementi in contesto lista:

    my @carte = ( 2 .. 10, 'J', 'Q', 'K', 'A' );

Può produrre dei semplici intervalli incrementali (sia di interi che di stringhe), ma non è capace di intuire pattern di intervalli più complessi.

In contesto booleano, l'operatore di intervallo diventa l'operatore flip-flop. Questo operatore produce un valore falso fino a quando il suo operando sinistro non diventa vero. Tale valore rimane vero fino a quando l'operando destro non diventa vero, dopo di che il valore prodotto è di nuovo falso fino a quando l'operatore sinistro non diventa di nuovo vero. Immaginate di effettuare il parsing del testo di una lettera formale con:

    while (/Hello, $user/ .. /Sincerely,/)
    {
        say "> $_";
    }

L'operatore virgola (,) è un operatore infisso. In contesto scalare valuta il suo operando sinistro e quindi restituisce il valore prodotto dalla valutazione del suo operando destro. In contesto lista, valuta entrambi gli operatori da destra a sinistra.

L'operatore fat comma (=>) effettua anche la quotatura di una bareword che compaia come suo operando sinistro (Hash).