Concetto basilare in Perl, il contesto è quello
nel quale una variabile o una sezione di codice sono valutati, e indica
il tipo di valore che si vuole ottenere in una determinata situazione.
Naturalmente il contesto sta ad indicare anche il tipo di valore che
possiamo assegnare ad un particolare tipo di variabile. In questo
documento parleremo dei tipi di dato ammissibili in Perl, nell'ottica
del concetto di contesto che verrà finalizzato in seguito.
dati scalari
chiamati literals o literal data (dati letterali), sono dei valori: numeri o stringhe:
espressioni
un'espressione è una entità che viene valutata in un valore, ad
esempio tramite operatori numerici (+ - * / ** %) oppure operatori su
stringhe (. e x)
undef
è il valore indefinito e non è propriamente un tipo di dato, ma indica
l'assenza di un valore in una variabile. Può essere pensato, per
comodità, come un tipo di dato con un solo possibile valore: NULL.
Possiamo assegnare il valore indefinito ad uno scalare, per cui il
valore indefinito può anche essere pensato come un caso speciale di
valore scalare.
liste
una lista è una collezione ordinata e finita di valori scalari o di
espressioni, separate da virgole. Viene costruita mediante l'operatore
virgola "," che concatena tra di loro degli scalari per produrre un
valore di lista. Di norma, visto che la precedenza dell'operatore "," è
molto bassa, per disambiguarne il comportamento si racchiude la lista
tra parentesi tonde.
per ottenere un singolo elemento della lista basta mettere un indice alla fine della lista:
Una volta definita, una lista non può crescere o diminuire come numero di elementi.
Quale costruttore di liste può essere usato l'operatore qw (detto word list, lista di parole), come ad esempio in
variabili scalari
chiamate semplicemente anche scalari, sono degli slot di memoria
associati ad un nome, nei quali si può immagazzinare un singolo dato,
che può essere:
Le variabili scalari vengono sempre prefissate da un carattere $ (che potremmo pensare come la s di scalar).
variabili aggregate (array)
contengono una lista di scalari: sono liste a cui è data la
capacità di crescere illimitatamente, diminuire, ed essere manipolate
che è lo stesso che scrivere
che quindi diventa
Gli array sono ordinati, nel senso che esiste un indice numerico
che si riferisce alla posizione, che ci permette di accedere al singolo
elemento della lista:
dunque ci si riferisce ad un elemento di un array facendolo
precedere dal simbolo $ e non dal @, infatti gli array sono liste di
scalari, dunque un singolo elemento è di fatto un singolo scalare, che è dunque denotato con il simbolo $ .
L'assegnamento di un array è equivalente all'assegnamento tra liste, infatti quello che avviene in
è questo:
L'assegnamento appena visto non avviene solo per elementi di array (che sono scalari) ma per ogni lista di scalari:
quest'ultima riga è possibile perchè; la parte destra
dell'assegnamento viene valutata per prima, dunque viene prima creata
la lista di destra che viene poi assegnata alla lista di variabili alla
sinistra.
Lo "slice" è una lista che viene estratta da un array mediante:
- un range di indici grazie all'operatore range ".." che nel caso seguente restituisce la lista (2, 3, 4)
- oppure attraverso un insieme di indici:
- oppure attraverso un insieme di range di indici:
Gli slice sono usati anche per modificare il valore di un array
- non siamo costretti a cambiare un singolo elemento di un array alla volta, ma possiamo cambiarne più di uno alla volta:
- se alla destra dell'assegnamento "offro" più elementi del necessario, questi vengono ignorati:
La funzione splice (perldoc -f splice) sostituisce parti di un
array con liste e restituisce la lista di elementi sostituiti. Nel caso
volessimo rimuovere uno o più elementi di un array, basta lasciare
vuota la lista di sostituzione:
variabili aggregate (hash)
chiamate anche array associativi, sono una collezione di valori
scalari (ne possono contenere un numero illimitato) e sono definiti
tramite coppie di chiavi e valori.
Non sono liste, ma le liste vengono spesso usate per definirli:
è una lista di coppie "chiave-valore", che � come dire
i valori degli hash possono essere scalari ma le chiavi devono essere stringhe, per cui vanno racchiuse tra virgolette:
'elemento_a'
L'operatore => ("fat comma", virgola grassa) è usato per
agevolare l'assegnamento di valori agli hash in modo da chiarire, a
livello di "occhiata" al codice che non si tratta di una semplice
lista:
In questo caso è subito chiaro che si tratta di coppie
chiave-valore, inoltre il quoting delle stringhe non è più necessario
visto che l'operatore => tratta l'operando alla sua sinistra come
una stringa. L'assegnamento di un hash diventa dunque:
La "fat comma" tratta l'operando a sinistra come una stringa solo
se ha lo stesso formato di un identificatore in particolare, in $ciao
=> 'a tutti', $ciao non viene racchiuso tra virgolette doppie
automaticamente vista la presenza di $.
L'utilizzo di stringhe quali valori per gli indici non ci impedisce di usare variabili per memorizzare tali stringhe
Per utilizzare chiavi non banali, si possono usare il single e double quoting:
Per l'assegnamento si può utilizzare anche l'operatore qw:
Bisogna tenere a mente che i valori immagazzinati da un hash sono
scalari per cui per accedere ad un valore di un hash ci si riferirà
alla variabile prefissandola con il simbolo $
Da notare che la chiave è una stringa e andrebbe quotata per buona
regola, ma non è strettamente necessario (è necessario se vi sono
spazi): le parentesi comunicano già al Perl che si tratta di hash,
dunque di chiavi, dunque di stringhe (vale la stessa regola citata per
la "fat comma").
Possiamo anche estrarre valori multipli (dunque liste) utilizzando liste di chiavi:
Davanti al nome di un hash si utilizza in questo caso @ perchè; si sta richiedendo una lista di valori.
Si può cambiare un valore di un hash: se è gia presente la chiave, esso verrà sovrascritto
altrimenti verrà aggiunto a quelli esistenti
Come per la lettura di valori, anche per l'inserimento si possono usare le liste, nel seguente modo:
ad esempio:
che è equivalente a:
Si possono anche costruire hash tramite range:
ed anche leggerne i valori:
Per cancellare un valore, lasciando però la chiave, si utilizza la funzione undef (perldoc -f undef)
Per eliminare del tutto la coppia chiave-valore, si utilizza la funzione delete (perldoc -f delete)
riferimenti (reference)
Quando si è parlato della variabile scalare, si è detto che è uno
slot di memoria che può contenere dati, a cui è associato un nome. Tale
slot di memoria, viene individuato fisicamente attraverso un indirizzo,
ed il Perl internamente mantiene una sua lista di associazioni
nome-indirizzo.
Il Perl dà la possibilità di assegnare ad una variabile l'indirizzo
di memoria di un'altra variabile. Questo è detto assegnamento di un
(hard) reference ad una variabile e si indica in questo modo:
In questo caso $variabile_riferimento è una normale variabile Perl
che contiene uno scalare, che noi sappiamo essere un indirizzo di
memoria che contiene lo scalare ospitato dalla variabile $variabile.
Tale indirizzo di memoria avrà una sua rappresentazione interna in Perl
e sarà qualcosa tipo: SCALAR(0x8070df7)
Per utilizzare il riferimento per accedere al valore della
variabile a cui il riferimento "punta", occorre deferenziare il
riferimento. Il Perl si aspetta di trovare dopo il simbolo $ , un
qualcosa che gli permetta di avere subito un indirizzo. Infatti
trovando il nome di una variabile, tramite l'accoppiata nome-indirizzo
di memoria, il Perl ha subito a disposizione tale indirizzo. Dunque se
si fa seguire al $ qualcosa che contiene un indirizzo di memoria allora
siamo a posto. Ma dato che nel nostro esempio $variabile_riferimento
contiene l'indirizzo di memoria di $variabile, allora facendo:
noi possiamo accedere direttamente al valore di $variabile.
In $$pluto, Perl trova un primo segno $ e va alla ricerca di
un'informazione che porti ad un indirizzo. Trova $pluto e in $pluto c'è
l'indirizzo valido di $pippo. Dunque userà questo indirizzo per
prelevarvi il valore contenuto: 42.
Un riferimento è sempre un valore scalare (contiene, tra le altre
cose, la rappresentazione interna che il Perl ha di un indirizzo di
memoria che non è altro che un numero) ma naturalmente può fare
riferimento anche all'indirizzo di memoria di un array o di un hash:
Anche in questo caso, dopo il simbolo @, il Perl si aspetta di
trovare una informazione che lo porti ad un indirizzo di memoria
valido. Per i singoli elementi di un array (o di un hash) che sono
scalari, vale quanto visto prima:
Cosa succede se si tenta di deferenziare un valore che non è un
hard reference? Tale valore viene trattato come riferimento simbolico
(symbolic reference), cioè il riferimento è interpretato come una
stringa che rappresenta il nome di una variabile (globale).
filehandle
Un filehandle è una sorta di linea di comunicazione tra il
programma e un canale (file, device, socket, pipe) di input (e.g.
tastiera) o di output (e.g. video). Se si pensa alla variabile come
associazione nome-indirizzo di memoria, un filehandle può essere
pensato come una associazione nome-canale di comunicazione.
Il filehandle nasconde dunque tutta una complicata struttura di
informazioni che implementa la linea di comunicazione tra programma e
device. Quando si vorrà scrivere o leggere su un canale, si scriverà
sul o si leggerà dal filehandle.
Le variabili di tipo filehandle non hanno alcun simbolo davanti al
nome e, per convenzione, i nomi di filehandle sono scritti con tutte le
lettere maiuscole. Quando un programma Perl viene eseguito esso ha già
3 filehandle predefiniti "aperti" alla comunicazione: STDIN (standard
input), STDOUT (standard output) e STDERR (standard error), dove STDIN è associato alla tastiera e STDOUT e STDERR al video. Dunque quando
scriviamo
è come se noi stessimo scrivendo
typeglob
Il typeglob è un tipo di dato composto che contiene una istanza di
ogni altro tipo di dato. è un amalgama (in gergo Perl: un glob) di
tutti gli altri tipi di dati dai quali condivide il nome: � una sorta
di super-riferimento il cui valore non è un singolo indirizzo ma un
qualcosa che ha 6 slot, 6 posizioni che contengono 6 differenti
riferimenti:
scalar
array
hash
code
handle
format
Viene utilizzato per scopi avanzati (come il passaggio di
filehandle alle subroutine, nel qual caso però si è soliti usare
librerie apposite oppure i filehandle lessicali, $fh).
Una variabile glob viene preceduta dal simbolo * e ad essa possono essere assegnati i riferimenti dei vari tipi di dato:
Per accedere ai valori della variabile glob (che sono riferimenti), nelle versioni più
recenti di Perl si può fare così:
Contesto
Dopo questa panoramica sui tipi di dato del Perl, passiamo ad elencare i tipi di contesto:
contesto scalare
si ha quando viene richiesto (l'utilizzo di) un singolo valore
Ma cosa succede se assegno una lista ad uno scalare?
Il contesto 'vincente' è quello della variabile dunque in questo caso il contesto è scalare. Quindi con:
forzo la valutazione di una lista in un contesto scalare. Dato che
in uno scalare posso memorizzare un solo valore, otterrò che in
$variabile ci sarà l'ultimo valore della lista: 'stringhe'.
Un caso particolare è l'assegnamento di un array ad uno scalare:
in questo caso (contesto scalare), $variabile conterrà il numero di elementi dell'array.
Nel caso in cui sia un hash ad essere assegnato ad uno scalare:
$variabile, se l'hash è vuoto, conterrà 0, altrimenti conterrà una
stringa composta dal numero di bucket usati e dal numero di bucket
allocati, separati da uno / (un bucket è lo slot di memoria nel quale
si memorizza il valore associato ad una chiave)
contesto di lista
si ha quando viene richiesto (l'utilizzo di) una lista di 0 o più valori
Ma cosa succede se assegno uno scalare ad una variabile in contesto di lista?
Il contesto 'vincente è quello della variabile e dunque il contesto è quello di lista.
Dunque con:
forzo la valutazione di uno scalare in un contesto di stringa. In
questo caso lo scalare viene convertito in stringa e poi assegnato alla
variabile @array.
Ciò è equivalente a :
Anche gli hash sono assegnati in un contesto di lista, per cui
assegnare uno scalare ad un hash è come definire un hash che ha una
sola chiave che fa coppia con un valore indefinito. Infatti lo scalare
viene convertito in una lista che ha 1 solo elemento che dunque diventa
l'unica chiave dell'hash (senza però alcun valore associato).
contesto booleano
esiste nel caso in cui un'espressione viene valutata per vedere se
essa sia vera o falsa. Avviene dunque in contesti condizionali: alcuni
operatori che in un contesto di lista si comportano in una certa
maniara, se sottoposti a verifica condizionale (dunque in un contesto
booleano) si comportano in un'altra.
contesto vuoto (void)
quando non viene richiesto alcun valore; avviene di rado, quando ad
esempio si usa un valore ma senza usarlo o assegnarlo, come in:
contesto interpolativo
avviene all'interno delle virgolette doppie (double quotes ") o con
operatori che hanno comportamenti analoghi alle virgolette doppie
(dunque che hanno a che fare con l'interpolazione di variabili) come ad
esempio l'operatore qq (perlodc -f qq).
Citiamo infine due funzioni predefinite del Perl che hanno a che fare con il contesto.
wantarray()
è una funzione da utilizzare in una subroutine per capire in che contesto � stata chiamata tale subroutine.
Chiamate di funzione:
scalar
viene usata quando si vuole forzare la valutazione di
un'espressione in contesto scalare, ovvero quando la valutazione della
stessa in contesto di lista avrebbe un diverso comportamento
(producendo dunque un diverso risultato), ad esempio:
Non esiste una funzione di lista corrispondente a scalar (ovvero
che da singolo scalare lo promuova a lista) visto che ogni operazione
che vuole una lista, fornisce già un contesto di lista ai suoi
argomenti.
Riferimenti
Professional Perl Programming della Wrox (ora ne esiste una versione riveduta: Pro Perl della Apress)
Geek0x90.org
Advertisement