Operatori
Gli operatori sono i mattoni fondamentali per costruire espressioni in qualsiasi linguaggio di programmazione. Lua offre un insieme completo di operatori aritmetici, relazionali, logici e di altro tipo. In questo articolo li analizzeremo tutti nel dettaglio, con esempi pratici e gli idiomi piu comuni.
Operatori Aritmetici
Lua supporta tutti gli operatori aritmetici standard, inclusa la divisione intera introdotta in Lua 5.3:
| Operatore | Descrizione | Esempio | Risultato |
|---|---|---|---|
+ |
Addizione | 10 + 3 |
13 |
- |
Sottrazione | 10 - 3 |
7 |
* |
Moltiplicazione | 10 * 3 |
30 |
/ |
Divisione (float) | 10 / 3 |
3.3333 |
// |
Divisione intera | 10 // 3 |
3 |
% |
Modulo (resto) | 10 % 3 |
1 |
^ |
Esponenziazione | 2 ^ 10 |
1024.0 |
- |
Negazione unaria | -42 |
-42 |
Vediamo gli operatori in azione:
local a, b = 17, 5
-- Operazioni di base
print("Addizione: " .. a + b) --> 22
print("Sottrazione: " .. a - b) --> 12
print("Moltiplicazione:" .. a * b) --> 85
-- Divisione float vs divisione intera
print("Divisione / " .. a / b) --> 3.4
print("Divisione // " .. a // b) --> 3
-- Modulo
print("Modulo: " .. a % b) --> 2
-- Esponenziazione (restituisce sempre float)
print("Potenza: " .. 2 ^ 8) --> 256.0
-- Negazione unaria
local x = 10
print("Negazione: " .. -x) --> -10
Divisione Intera e Modulo
La divisione intera // arrotonda sempre verso il basso (verso meno infinito), e il modulo segue la stessa convenzione:
-- Divisione intera con numeri negativi
print(7 // 2) --> 3
print(-7 // 2) --> -4 (arrotonda verso -infinito)
print(7 // -2) --> -4
-- Il modulo rispetta l'identita: a % b == a - (a // b) * b
print(7 % 3) --> 1
print(-7 % 3) --> 2 (sempre non-negativo con divisore positivo)
-- Uso pratico: verificare se un numero e pari
local numero = 42
if numero % 2 == 0 then
print(numero .. " e pari") --> 42 e pari
end
Esponenziazione
L’operatore ^ restituisce sempre un valore float, anche con operandi interi:
print(2 ^ 10) --> 1024.0 (float, non integer)
print(type(2 ^ 10)) --> number
print(math.type(2 ^ 10)) --> float
-- Radice quadrata tramite esponenziazione
print(25 ^ 0.5) --> 5.0
print(27 ^ (1/3)) --> 3.0 (radice cubica)
Operatori Relazionali
Gli operatori relazionali confrontano due valori e restituiscono un booleano (true o false):
| Operatore | Descrizione | Esempio | Risultato |
|---|---|---|---|
== |
Uguale a | 5 == 5 |
true |
~= |
Diverso da | 5 ~= 3 |
true |
< |
Minore di | 3 < 5 |
true |
> |
Maggiore di | 5 > 3 |
true |
<= |
Minore o uguale | 5 <= 5 |
true |
>= |
Maggiore o uguale | 5 >= 3 |
true |
Nota importante: in Lua l’operatore di disuguaglianza e ~=, non != come in C, Java o Python.
local a, b = 10, 20
print(a == b) --> false
print(a ~= b) --> true
print(a < b) --> true
print(a > b) --> false
print(a <= 10) --> true
print(a >= 20) --> false
-- Confronto tra stringhe (ordine lessicografico)
print("abc" < "abd") --> true
print("abc" < "ab") --> false
print("abc" == "abc") --> true
-- Le tabelle vengono confrontate per riferimento, non per contenuto
local t1 = {1, 2, 3}
local t2 = {1, 2, 3}
local t3 = t1
print(t1 == t2) --> false (oggetti diversi in memoria)
print(t1 == t3) --> true (stesso riferimento)
Operatori Logici
Lua dispone di tre operatori logici: and, or e not. La loro particolarita e che and e or restituiscono uno degli operandi, non necessariamente un booleano:
| Operatore | Descrizione | Comportamento |
|---|---|---|
and |
E logico | Restituisce il primo operando falso, o l’ultimo |
or |
O logico | Restituisce il primo operando vero, o l’ultimo |
not |
Negazione | Restituisce true o false |
-- Comportamento di "and"
print(true and "ciao") --> ciao (primo e vero, restituisce il secondo)
print(false and "ciao") --> false (primo e falso, restituisce il primo)
print(nil and "ciao") --> nil (nil e falso)
print("a" and "b") --> b (entrambi veri, restituisce il secondo)
-- Comportamento di "or"
print(true or "ciao") --> true (primo e vero, restituisce il primo)
print(false or "ciao") --> ciao (primo e falso, restituisce il secondo)
print(nil or "default") --> default
print("a" or "b") --> a (primo e vero, restituisce il primo)
-- Comportamento di "not"
print(not true) --> false
print(not false) --> true
print(not nil) --> true
print(not "ciao") --> false (le stringhe sono truthy)
print(not 0) --> false (0 e truthy in Lua!)
Cortocircuito (Short-Circuit Evaluation)
Gli operatori and e or usano la valutazione a cortocircuito: se il risultato e determinato dal primo operando, il secondo non viene valutato:
-- La funzione costosa() non viene mai chiamata
local risultato = false and costosa() -- restituisce false
local risultato = true or costosa() -- restituisce true
Idioma: Valore di Default con “or”
Uno degli idiomi piu usati in Lua sfrutta or per assegnare valori di default:
-- Se "nome" e nil o false, usa "Sconosciuto"
local nome = nil
local nome_visualizzato = nome or "Sconosciuto"
print(nome_visualizzato) --> Sconosciuto
-- Funzione con parametro opzionale
local function saluta(nome)
nome = nome or "Mondo"
print("Ciao, " .. nome .. "!")
end
saluta("Lua") --> Ciao, Lua!
saluta() --> Ciao, Mondo!
Attenzione: questo idioma non funziona se false e un valore valido:
-- Problema: false viene trattato come "assente"
local attivo = false
local valore = attivo or true -- restituisce true, non false!
Idioma: Operatore Ternario Simulato
Lua non ha un operatore ternario (? : come in C), ma lo si puo simulare con and/or:
-- Equivalente di: risultato = condizione ? valore_vero : valore_falso
local x = 10
local segno = (x > 0) and "positivo" or "non positivo"
print(segno) --> positivo
-- Altro esempio
local eta = 20
local categoria = (eta >= 18) and "adulto" or "minorenne"
print(categoria) --> adulto
Operatore di Concatenazione (…)
L’operatore .. concatena due stringhe. Se un operando e un numero, viene automaticamente convertito in stringa:
local nome = "Lua"
local versione = 5.4
local messaggio = "Benvenuto in " .. nome .. " " .. versione .. "!"
print(messaggio) --> Benvenuto in Lua 5.4!
-- Concatenazione ripetuta (usa table.concat per efficienza)
local parti = {}
for i = 1, 5 do
parti[i] = "parte" .. i
end
local risultato = table.concat(parti, ", ")
print(risultato) --> parte1, parte2, parte3, parte4, parte5
Per concatenazioni ripetute in un ciclo, e piu efficiente raccogliere le parti in una tabella e usare table.concat().
Operatore di Lunghezza (#)
L’operatore # restituisce la lunghezza di una stringa (in byte) o di una sequenza in una tabella:
-- Lunghezza delle stringhe
local s = "Ciao Mondo"
print(#s) --> 10
-- Lunghezza delle sequenze (tabelle con indici numerici consecutivi da 1)
local lista = {"a", "b", "c", "d"}
print(#lista) --> 4
-- Attenzione: con tabelle che hanno "buchi", il comportamento e indefinito
local t = {1, nil, 3}
print(#t) -- risultato imprevedibile (potrebbe essere 1 o 3)
-- Uso pratico: aggiungere un elemento alla fine di una tabella
local numeri = {10, 20, 30}
numeri[#numeri + 1] = 40
print(numeri[4]) --> 40
Precedenza degli Operatori
La tabella seguente elenca gli operatori dalla precedenza piu alta alla piu bassa:
1. ^ (esponenziazione, associativo a destra)
2. not # - (operatori unari)
3. * / // % (moltiplicazione e divisione)
4. + - (addizione e sottrazione)
5. .. (concatenazione, associativo a destra)
6. < > <= >= ~= == (comparazione)
7. and (e logico)
8. or (o logico)
In caso di dubbio, usa le parentesi per rendere esplicita la precedenza:
-- Senza parentesi
local r = 2 + 3 * 4 -- 14 (la moltiplicazione ha precedenza)
-- Con parentesi per chiarezza
local r = 2 + (3 * 4) -- 14, piu chiaro
local r = (2 + 3) * 4 -- 20, comportamento diverso
-- L'esponenziazione e associativa a destra
print(2 ^ 2 ^ 3) --> 256 (equivale a 2 ^ (2 ^ 3) = 2 ^ 8)
-- La concatenazione e associativa a destra
local s = "a" .. "b" .. "c" -- equivale a "a" .. ("b" .. "c")
Riepilogo Pratico
Ecco un esempio completo che utilizza diversi operatori:
-- Calcolo del prezzo finale con sconto
local function calcola_prezzo(prezzo_base, sconto_percentuale, tasse)
sconto_percentuale = sconto_percentuale or 0
tasse = tasse or 22
local sconto = prezzo_base * sconto_percentuale / 100
local prezzo_scontato = prezzo_base - sconto
local importo_tasse = prezzo_scontato * tasse / 100
local prezzo_finale = prezzo_scontato + importo_tasse
return prezzo_finale
end
local prezzo = calcola_prezzo(100, 15)
print("Prezzo finale: " .. string.format("%.2f", prezzo) .. " EUR")
--> Prezzo finale: 103.70 EUR
Conclusione
Gli operatori di Lua coprono tutte le necessita della programmazione quotidiana. La particolarita piu importante da ricordare e il comportamento degli operatori logici and e or, che restituiscono gli operandi stessi anziche un semplice booleano. Questo permette di scrivere codice conciso e idiomatico, come il pattern a = a or valore_default, che e onnipresente nel codice Lua di qualita.