In molti linguaggi C-like e' possibile concatenare istruzioni di assegnamento in una sola:
a = b = foo();
con il risultato che gli operandi a sinistra dell'ultimo simbolo '=' sono trattati tutti come lvalue e assegnati al valore rvalue simultaneamente, ovvero come se si fosse diviso l'assegnamento:
b = foo();
a = b;
In Perl la concatenazione degli assegnamenti potrebbe non seguire le stesse regole. O meglio, siccome in Perl e' lecito assegnare valori di tipo diverso fra loro, ogni operatore di assegnamento segue le regole del rispettivo lvalue. Per dimostrare questo fatto, tutto sommato semplice da capire ma che puo' rivelarsi molto subdolo, e' possibile considerare il seguente semplice programma:
#!/usr/bin/env perl -w
use v5.10;
sub foo{
return qw(Hello LIST World) if wantarray;
return "Hello World";
}
$scalar = foo();
@array = foo();
say "The scalar value is < $scalar >";
say "The array values are < @array >";
che produce l'atteso output che segue:
The scalar value is < Hello World >
The array values are < Hello LIST World >
Il trucco e' semplice e ben noto: in Perl ogni cosa avviene in un contesto specifico e wantarray e' capace di fornire il contesto di chiamata della funzione consentendo una sorta di sovraccarico del valore di ritorno.
Ma analizziamo un'assegnamento piu' complesso:
$scalar = @array = foo();
L'output prodotto e' il seguente:
The scalar value is < 3 >
The array values are < Hello LIST World >
Cosa e' successo?
Per prima cosa viene valutato il rvalue dell'espressione, ossia foo(): tale funzione viene chiamata in un contesto di lista poiche' il primo assegnamento del rvalue e' ad un array, e quindi @array diviene, correttamente, il contenitore della lista.
Successivamente @array viene assegnato a $scalar, ossia c'e' un assegnamento di lista in contesto scalare, e quindi si calcola la dimensione dell'array (3 appunto) e la si assegna a $scalar.
Una volta compreso questo, il seguente assegnamento produce lo stesso effetto finale su $scalar per ovvi motivi:
$scalar = () = foo();
E questo evidenzia come sia possibile mutare il comportamento delle funzioni forzando un contesto senza necessariamente passare per variabili temporanee.
Ma per cortesia, non scriviamo codice del genere (si pensi alla sanita' mentale degli altri programmatori che si troveranno davanti questa espressione)!
Nessun commento:
Posta un commento