00
:
00
:
00
:
00
•Corso SEO AI - Usa SEOEMAIL al checkout per il 30% di sconto

Variabili e Tipi di Dati

Lua e un linguaggio a tipizzazione dinamica: le variabili non hanno un tipo fisso, ma il tipo e associato al valore che contengono in un dato momento. Nonostante questa flessibilita, Lua dispone di un sistema di tipi preciso e ben definito. In questo articolo esploreremo tutti gli 8 tipi di dati di Lua, la gestione delle variabili e le regole di coercizione.

Gli 8 Tipi di Dati di Lua

Lua ha esattamente 8 tipi fondamentali. Puoi verificare il tipo di qualsiasi valore con la funzione type():

print(type(nil))            --> nil
print(type(true))           --> boolean
print(type(42))             --> number
print(type("ciao"))         --> string
print(type(print))          --> function
print(type({}))             --> table
print(type(io.stdin))       --> userdata
print(type(coroutine.create(function() end)))  --> thread

La funzione type() restituisce sempre una stringa con il nome del tipo.

1. nil

nil rappresenta l’assenza di valore. E l’unico valore del tipo nil e ha un ruolo fondamentale in Lua:

local x                 -- x vale nil (non inizializzata)
print(x)                --> nil
print(type(x))          --> nil

-- nil e usato per "eliminare" variabili e campi di tabelle
local t = {a = 1, b = 2}
t.b = nil               -- rimuove il campo "b" dalla tabella

In un contesto booleano, nil e considerato falso.

2. boolean

Il tipo boolean ha solo due valori: true e false:

local attivo = true
local errore = false

print(type(attivo))     --> boolean

-- In Lua, solo nil e false sono "falsy"
-- Tutto il resto e "truthy", incluso 0 e la stringa vuota!
if 0 then
    print("0 e truthy in Lua!")        --> viene stampato!
end

if "" then
    print("Stringa vuota e truthy!")   --> viene stampato!
end

Questa e una differenza importante rispetto a linguaggi come Python o JavaScript, dove 0 e "" sono considerati falsi.

3. number

In Lua 5.4, i numeri si dividono in integer (interi a 64 bit) e float (virgola mobile a doppia precisione):

local intero = 42
local decimale = 3.14
local esponenziale = 1.5e10
local esadecimale = 0xFF        -- 255

print(type(intero))             --> number
print(type(decimale))           --> number

-- Verifica se un numero e intero o float
print(math.type(42))            --> integer
print(math.type(42.0))          --> float

-- Conversione tra integer e float
print(42 + 0.0)                 --> 42.0 (diventa float)
print(math.tointeger(42.0))     --> 42 (diventa integer)

-- Divisione intera vs divisione float
print(7 / 2)                    --> 3.5 (divisione float)
print(7 // 2)                   --> 3   (divisione intera)

4. string

Le stringhe in Lua sono sequenze immutabili di byte. Possono essere definite con apici singoli, doppi o doppie parentesi quadre:

local s1 = "Ciao Mondo"
local s2 = 'Anche gli apici singoli funzionano'
local s3 = [[
Stringa su
piu righe
]]

-- Le stringhe sono immutabili
local nome = "Lua"
-- nome[1] = "l"  -- ERRORE: non puoi modificare una stringa

-- Lunghezza di una stringa
print(#nome)                    --> 3

-- Concatenazione
local saluto = "Ciao" .. " " .. nome
print(saluto)                   --> Ciao Lua

-- Sequenze di escape comuni
local speciali = "Tab:\tNuova riga:\nBackslash:\\"
print(speciali)

5. function

In Lua le funzioni sono valori di prima classe: possono essere assegnate a variabili, passate come argomenti e restituite da altre funzioni:

-- Funzione assegnata a una variabile
local somma = function(a, b)
    return a + b
end

print(type(somma))              --> function
print(somma(3, 4))              --> 7

-- Funzione come argomento
local function applica(fn, x, y)
    return fn(x, y)
end

print(applica(somma, 10, 20))   --> 30

-- La stessa print e una funzione
print(type(print))              --> function

6. table

La tabella e l’unica struttura dati composita in Lua. Serve come array, dizionario, oggetto, modulo e molto altro:

-- Tabella come array (indici numerici, partono da 1)
local frutti = {"mela", "pera", "banana"}
print(frutti[1])                --> mela
print(#frutti)                  --> 3

-- Tabella come dizionario (coppie chiave-valore)
local persona = {
    nome = "Marco",
    eta = 30,
    citta = "Roma"
}
print(persona.nome)             --> Marco
print(persona["eta"])           --> 30

-- Tabelle miste
local mista = {
    "primo",                     -- indice 1
    chiave = "valore",           -- chiave stringa
    [10] = "decimo",             -- indice numerico esplicito
}

7. userdata

Il tipo userdata rappresenta dati C arbitrari memorizzati in variabili Lua. E utilizzato principalmente per l’interfacciamento con librerie C:

-- Esempio: i file handle sono userdata
local file = io.open("test.txt", "r")
if file then
    print(type(file))           --> userdata
    file:close()
end

I programmatori Lua comuni raramente creano userdata direttamente; vengono forniti dalle librerie C.

8. thread

Il tipo thread rappresenta una coroutine, un flusso di esecuzione indipendente:

local co = coroutine.create(function()
    print("Dentro la coroutine")
    coroutine.yield()
    print("Ripresa la coroutine")
end)

print(type(co))                 --> thread
coroutine.resume(co)            --> Dentro la coroutine
coroutine.resume(co)            --> Ripresa la coroutine

Variabili Locali e Globali

In Lua, le variabili sono globali per default. Si usa la parola chiave local per dichiarare variabili locali:

-- Variabile globale (SCONSIGLIATA nella maggior parte dei casi)
contatore = 0

-- Variabile locale (CONSIGLIATA)
local risultato = 42

-- Le variabili locali sono limitate al blocco in cui sono dichiarate
do
    local temp = 100
    print(temp)                 --> 100
end
-- print(temp)                  --> nil (temp non esiste piu)

E una best practice usare sempre local per le variabili. Le variabili globali inquinano il namespace, sono piu lente da accedere e rendono il codice piu difficile da mantenere:

-- SBAGLIATO: troppe variabili globali
nome = "Mario"
cognome = "Rossi"
eta = 25

-- CORRETTO: usa sempre local
local nome = "Mario"
local cognome = "Rossi"
local eta = 25

Tipizzazione Dinamica

In Lua il tipo e associato al valore, non alla variabile. La stessa variabile puo contenere valori di tipi diversi in momenti diversi:

local x = 10            -- x contiene un number
print(type(x))          --> number

x = "adesso sono una stringa"
print(type(x))          --> string

x = true
print(type(x))          --> boolean

x = {1, 2, 3}
print(type(x))          --> table

x = nil
print(type(x))          --> nil

Coercizione dei Tipi

Lua effettua automaticamente la coercizione (conversione implicita) tra stringhe e numeri in alcuni contesti:

-- Stringa convertita in numero nelle operazioni aritmetiche
print("10" + 5)                 --> 15
print("3.14" * 2)               --> 6.28

-- Numero convertito in stringa nella concatenazione
print(42 .. " gatti")           --> 42 gatti
print(type(42 .. ""))           --> string

-- Conversione esplicita (consigliata per chiarezza)
local s = tostring(42)          -- "42"
local n = tonumber("3.14")      -- 3.14

-- Attenzione: la conversione puo fallire
local risultato = tonumber("abc")
print(risultato)                --> nil (conversione fallita)

E buona pratica preferire la conversione esplicita con tonumber() e tostring() invece di affidarsi alla coercizione automatica.

Assegnamento Multiplo

Lua supporta l’assegnamento multiplo, permettendo di assegnare piu valori a piu variabili in una singola istruzione:

-- Assegnamento multiplo
local x, y, z = 10, 20, 30
print(x, y, z)                  --> 10  20  30

-- Se ci sono piu variabili che valori, le extra valgono nil
local a, b, c = 1, 2
print(a, b, c)                  --> 1  2  nil

-- Se ci sono piu valori che variabili, i valori extra sono scartati
local p, q = 10, 20, 30
print(p, q)                     --> 10  20

-- Scambio di variabili in una riga (idiomatico in Lua)
local primo, secondo = "A", "B"
primo, secondo = secondo, primo
print(primo, secondo)           --> B  A

L’assegnamento multiplo e particolarmente utile con le funzioni che restituiscono piu valori:

-- Le funzioni possono restituire piu valori
local function dividi(a, b)
    return a // b, a % b    -- quoziente e resto
end

local quoziente, resto = dividi(17, 5)
print("17 / 5 = " .. quoziente .. " con resto " .. resto)
--> 17 / 5 = 3 con resto 2

Conclusione

Il sistema di tipi di Lua e semplice ma completo. Con soli 8 tipi fondamentali, il linguaggio offre tutta la flessibilita necessaria per costruire programmi complessi. La regola d’oro e usare sempre local per le variabili, preferire le conversioni esplicite alla coercizione automatica e sfruttare l’assegnamento multiplo per scrivere codice piu pulito e idiomatico.