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

Funzioni in Lua

Le funzioni sono uno dei pilastri fondamentali di Lua. In Lua le funzioni sono valori di prima classe: possono essere assegnate a variabili, passate come argomenti e restituite da altre funzioni. In questa guida esploreremo tutti gli aspetti delle funzioni in Lua, dalla dichiarazione di base fino alle funzioni variadiche e alle closure.

Dichiarazione di una Funzione

La sintassi base per dichiarare una funzione in Lua e’ la seguente:

function nomeFunzione(parametri)
    -- corpo della funzione
end

Ecco un esempio semplice:

function saluta(nome)
    print("Ciao, " .. nome .. "!")
end

saluta("Marco")
-- Output: Ciao, Marco!

In realta’, la sintassi sopra e’ uno zucchero sintattico per:

saluta = function(nome)
    print("Ciao, " .. nome .. "!")
end

Questo dimostra che le funzioni in Lua sono semplicemente valori assegnati a variabili.

Parametri e Argomenti

Le funzioni possono accettare zero o piu’ parametri. In Lua, se si passano piu’ argomenti del necessario, quelli in eccesso vengono ignorati. Se se ne passano meno, i parametri mancanti assumono il valore nil:

function mostra(a, b, c)
    print(a, b, c)
end

mostra(1, 2, 3)       -- Output: 1    2    3
mostra(1, 2)           -- Output: 1    2    nil
mostra(1, 2, 3, 4)    -- Output: 1    2    3  (il 4 viene ignorato)

Valori di Default

Lua non ha parametri con valori di default nativi, ma si puo’ simulare questo comportamento:

function connetti(host, porta)
    host = host or "localhost"
    porta = porta or 8080
    print("Connessione a " .. host .. ":" .. porta)
end

connetti()                  -- Connessione a localhost:8080
connetti("esempio.com")     -- Connessione a esempio.com:8080
connetti("esempio.com", 3000) -- Connessione a esempio.com:3000

Valori di Ritorno

Le funzioni possono restituire valori con l’istruzione return:

function somma(a, b)
    return a + b
end

local risultato = somma(10, 20)
print(risultato) -- Output: 30

Ritorni Multipli

Una caratteristica distintiva di Lua e’ la possibilita’ di restituire piu’ valori da una funzione:

function dividi(dividendo, divisore)
    local quoziente = math.floor(dividendo / divisore)
    local resto = dividendo % divisore
    return quoziente, resto
end

local q, r = dividi(17, 5)
print("Quoziente: " .. q .. ", Resto: " .. r)
-- Output: Quoziente: 3, Resto: 2

I ritorni multipli sono molto utili per restituire un risultato insieme a uno stato di errore:

function apri_file(percorso)
    local file = io.open(percorso, "r")
    if not file then
        return nil, "Impossibile aprire il file: " .. percorso
    end
    return file, nil
end

local f, errore = apri_file("dati.txt")
if not f then
    print("Errore: " .. errore)
end

Funzioni Variadiche

Le funzioni variadiche accettano un numero variabile di argomenti, indicati con ... (tre puntini):

function stampa_tutti(...)
    local args = {...}
    for i, v in ipairs(args) do
        print(i .. ": " .. tostring(v))
    end
end

stampa_tutti("mela", "banana", "arancia")
-- Output:
-- 1: mela
-- 2: banana
-- 3: arancia

Si possono combinare parametri fissi con quelli variadici:

function log(livello, ...)
    local messaggi = {...}
    for _, msg in ipairs(messaggi) do
        print("[" .. livello .. "] " .. msg)
    end
end

log("INFO", "Server avviato", "Porta 8080 in ascolto")
-- Output:
-- [INFO] Server avviato
-- [INFO] Porta 8080 in ascolto

Per conoscere il numero di argomenti variadici si usa select("#", ...):

function conta_args(...)
    print("Numero di argomenti: " .. select("#", ...))
end

conta_args(1, nil, 3)  -- Output: Numero di argomenti: 3

Funzioni come Valori di Prima Classe

In Lua le funzioni sono valori come numeri o stringhe. Possono essere assegnate a variabili, memorizzate in tabelle e passate come argomenti:

-- Assegnare una funzione a una variabile
local raddoppia = function(x) return x * 2 end
print(raddoppia(5)) -- Output: 10

-- Passare una funzione come argomento
function applica(fn, valore)
    return fn(valore)
end

print(applica(raddoppia, 7)) -- Output: 14

-- Memorizzare funzioni in una tabella
local operazioni = {
    somma = function(a, b) return a + b end,
    sottrai = function(a, b) return a - b end,
    moltiplica = function(a, b) return a * b end,
}

print(operazioni.somma(3, 4))       -- Output: 7
print(operazioni.moltiplica(3, 4))  -- Output: 12

Funzioni Anonime

Le funzioni anonime (lambda) sono funzioni senza nome, spesso usate come callback:

local numeri = {5, 2, 8, 1, 9, 3}

table.sort(numeri, function(a, b)
    return a > b  -- ordine decrescente
end)

for _, v in ipairs(numeri) do
    print(v)
end
-- Output: 9, 8, 5, 3, 2, 1

Funzioni Locali

Le funzioni dichiarate con local sono visibili solo nello scope corrente. E’ buona pratica utilizzare funzioni locali quando possibile:

local function calcola_area(base, altezza)
    return (base * altezza) / 2
end

print(calcola_area(10, 5)) -- Output: 25

Per le funzioni ricorsive locali, e’ necessario dichiarare la variabile prima della definizione:

local fattoriale
fattoriale = function(n)
    if n <= 1 then return 1 end
    return n * fattoriale(n - 1)
end

print(fattoriale(6)) -- Output: 720

Oppure si puo’ usare la forma abbreviata local function, che gestisce automaticamente questo caso:

local function fattoriale(n)
    if n <= 1 then return 1 end
    return n * fattoriale(n - 1)
end

Sintassi di Chiamata: Punto vs Due Punti

Quando le funzioni sono memorizzate nelle tabelle, Lua offre due sintassi di chiamata:

  • Punto (.): chiamata standard, si passa esplicitamente l’oggetto.
  • Due punti (:): zucchero sintattico che passa automaticamente la tabella come primo parametro self.
local giocatore = {
    nome = "Luigi",
    vita = 100,
}

function giocatore.saluta(self)
    print("Sono " .. self.nome)
end

-- Equivalente con la sintassi dei due punti
function giocatore:prendi_danno(danno)
    self.vita = self.vita - danno
    print(self.nome .. " ha ora " .. self.vita .. " HP")
end

giocatore.saluta(giocatore)   -- Sono Luigi
giocatore:prendi_danno(25)    -- Luigi ha ora 75 HP

-- Le due forme sono intercambiabili:
giocatore.prendi_danno(giocatore, 10) -- Luigi ha ora 65 HP
giocatore:saluta()                     -- Sono Luigi

Closure

Le funzioni in Lua possono catturare variabili dallo scope esterno, creando delle closure:

function crea_contatore(inizio)
    local conteggio = inizio or 0
    return function()
        conteggio = conteggio + 1
        return conteggio
    end
end

local contatore = crea_contatore(0)
print(contatore()) -- Output: 1
print(contatore()) -- Output: 2
print(contatore()) -- Output: 3

Conclusioni

Le funzioni in Lua sono estremamente flessibili grazie alla loro natura di valori di prima classe. La possibilita’ di restituire piu’ valori, di creare funzioni variadiche e di utilizzare closure rende Lua un linguaggio potente e espressivo. Comprendere la differenza tra la sintassi con il punto e quella con i due punti e’ essenziale per lavorare con le tabelle come oggetti. L’uso di funzioni locali e’ una buona pratica che migliora le prestazioni e la leggibilita’ del codice.