venerdì 13 marzo 2015

Corso Lua - puntata 2 - Assegnazione


L'assegnamento

Eccoci alla seconda puntata del corso base su Lua, il formidabile linguaggio di programmazione, veloce, semplice e utile. Dovreste aver accesso a un computer con l'interprete Lua già installato, se no, rileggete la puntata precedente per conoscere alcune informazioni di base per farlo. Così potrete eseguire il codice.

Oggi ci occuperemo di uno degli elementi di base dei linguaggi informatici: l'istruzione di assegnamento. Con questa operazione si introduce un simbolo nel programma associandolo a un valore appartenente a un dato tipo.

La sintassi di Lua non sorprende: a sinistra compare il nome della variabile e a destra l'espressione che fornirà il valore da assegnare mentre il carattere di "=" funge da simbolo semantico e separatore:
  a = 123
Durante l'esecuzione di questo programma Lua determina dinamicamente il tipo del valore letterale '123' --- un numero --- istanziandolo globalmente come simbolo 'a'. La semplice istruzione di assegnamento nasconde quindi due cose importanti di Lua: la prima è che non è necessario specificare esplicitamente il tipo dei dati come in altri linguaggi a tipi dinamici, e la seconda è che il tipo è determinato e associato al simbolo in modo automatico.

Modalità interattiva

Aprite un terminale, o console in Windows, e digitate semplicemente il comando lua. Entreremo nella modalità interattiva dove potremo digitare istruzioni una alla volta. Per uscire tornando al prompt, digitate la funzione Lua os.exit() con un bel tasto invio.

In modalità interattiva possiamo comodamente controllare quale tipo avrà un valore, utilizzando la funzione type(). Essa restituisce una stringa con il nome del tipo di un'espressione, stringa che possiamo a sua volta stampare con la funzione print(): stampa l'argomento in console. Digitiamo:

 a = 123
 print(type(123))    --> stampa "number"
 print(type(a))      --> stampa "number"
 print(type("123"))  --> stampa "string"


Locale o globale?

La seconda proprietà nascosta è che se non diversamente specificato Lua istanzia i simboli nell'ambiente globale del codice in esecuzione. Se si desidera creare una variabile locale sempre rispetto al blocco di codice in cui è definita, basta premettere la parola chiave local.

Le variabili locali evitano alcuni errori di programmazione e in Lua rendono il codice più veloce. Le useremo sempre quando un simbolo appartiene in modo semantico a un blocco, per esempio a una funzione.

Da notare che in sessione interattiva ogni riga è un blocco quindi le variabili locali non sopravvivono alla riga successiva. Perciò negli esempi in questa modalità useremo variabili globali.

Se si crea una variabile locale con una variabile globale quest'ultima viene oscurata e il suo valore protetto da modifiche.

Il tipo nil

Uno dei concetti più importanti che caratterizzano un linguaggio è la presenza o meno del tipo nullo. In Lua esiste e viene chiamato nil. Il tipo nullo ha un solo valore possibile anch'esso chiamato nil. Il nome è così sia l'unico valore possibile che il tipo.

Leggere una variabile non istanziata non è un errore perché Lua restituisce semplicemente nil, mentre assegnare il valore nullo a una variabile la distrugge.
Sempre in sessione interattiva:

 print(z)    --> stampa nil, la variabile 'z' non esiste
 z = 123     --> assegnamento di un tipo numerico
 print(z)    --> stampa 123
 z = nil     --> distruzione della variabile


Le variabili non più utili come quelle riassegnate a nil o quelle locali quando queste escono di scopo, vengono gestite automaticamente dal garbage collector di Lua. Questo componente semplifica la gestione della memoria al prezzo di una piccola diminuzione delle prestazioni.

Certamente se è un garbage collector a liberare dietro le quinte la memoria non più utilizzata il programma non conterrà gli errori tipici di questa gestione manuale.

Assegnazioni multiple

In Lua possono essere assegnate più variabili alla volta nella stessa istruzione.
Questo significa che l'assegnamento è in realtà più complesso di quello presentato fino a ora perché è possibile scrivere una lista di variabili separate da virgole che assumeranno il valore corrispondente in una lista di espressioni sempre separate da virgola:
 x, y, z = 1, 2, 3
 print(x, y, z)

Quando i nomi dei simboli non corrispondono alle espressioni Lua assegnerà automativamente valori nil o ignorerà le espresisoni in eccesso, per esempio sempre in sessione interattiva al terminale proviamo il seguente codice:
 a, b, c = 0.45, "text"  -- c è nil
 print(a, b, c)

 x, y = "op", "qw", "lo"
 print(x, y)  -- "lo" è ignorata

Nell'assegnazione Lua prima valuta le espressioni a destra e solo successivamente crea le rispettive variabili secondo l'ordine nelle liste. Allora per scambiare il valore di due variabili, operazione chiamata di switch, è sufficiente il codice:
 x, y = y, x


Un ulteriore esempio di assegnazione multipla è il seguente, a dimostrazione che le espressioni della lista a destra vengono prima valutate e solo dopo assegnate alle corrispondenti variabili nella lista di sinistra:
  -- costante
  pi = 3.14159
  -- raggio del cerchio
  r = 10.8
  -- grandezze principali del cerchio
  diam, circ, area = 2*r, 2*pi*r, pi*r^2

  -- stampa grandezze
  print("Diametro", diam)
  print("Circonferenza", circ)
  print("Area", area)

Le assegnazioni multiple sono interessanti ma non così importanti, possiamo infatti ricorrere ad assegnazioni semplici. Diverranno invece molto utili con le funzioni e gli iteratori di cui ci occuperemo nel seguito.

Una manciata di tipi

In Lua esiste una manciata di tipi. Essenzialmente omettendone due sono solo questi:
  • il tipo numerico (solamente dalla versione 5.3 di Lua vengono internamente distinti gli interi e i numeri in virgola mobile);
  • il tipo stringa;
  • il tipo booleano;
  • il tipo tabella;
  • il tipo nil;
  • il tipo funzione.

Il breve elenco può suscitare due osservazioni: tranne la tabella non esistono tipi strutturati e le funzioni hanno il rango di tipo.

Questo fa capire molto bene il carattere di Lua: da un lato l'essenzialità ha ridotto all'indispensabile i tipi predefiniti nel linguaggio ma dall'altro ha spinto all'inclusione di concetti intelligenti e potenti.

Esercizi

Scrivere un programma che instanzi due variabili 'x' e 'y' al valore 12.34 e assegnare a altre due variabili 'sum' e 'prod' la somma e il loro prodotto delle prime. Si stampi in console i risultati contenuti in 'sum' e 'prod'.

Scrivere un programma che dimostri che modificare una variabile locale non modifica il valore della variabile globale con lo stesso nome. Suggerimento: utilizzare la coppia do/end per creare un blocco di codice con le proprie variabili locali.

Riassunto della puntata

Ho tenuto al minimo le istruzioni da digitare per effettuare le prove di codice per non distogliere l'attenzione sui concetti fondamentali di Lua che riguardano le variabili che riassunti sono:
  • l'assegnazione semplice istanzia variabili globali;
  • il tipo nil è utilizzato per dare significato alle variabili non istanziate e per eliminare quelle istanziate;
  • l'assegnazione multipla si basa sulla corrispondenza di posizione nelle liste separate da virgole dei nomi e delle espressioni di valori.

Nella prossima puntata affronteremo la tabella, l'oggetto più importante in Lua. Dovremo conoscerlo bene per scrivere programmi utili.

Nessun commento:

Posta un commento