segue dalla seconda parte
Che fai tu luna in ciel ? : le funzioni
Fino a che scriviamo script di poche righe, possiamo inserire le istruzioni nel programma principale, ma aumentando la complessità diventa necessario organizzare il codice in pezzi indipendenti e riutilizzabili; come in tutti gli altri linguaggi, in Lua è possibile definire funzioni; vediamo un esempio piuttosto classico:
function fattoriale(n)
local f=1 -- variabile locale alla funzione
for i=2,n do
f=f*i
end
return f
Abbiamo definito la funzione fattoriale, che da ora in avanti possiamo richiamare nel nostro codice:
print(fattoriale(10))
Notiamo che la variabile f ha il prefisso local: questo perché per default in Lua le variabili sono globali se non viene esplicitato diversamente. Vediamo un esempio:
pippo,pluto=1,2
function func()
pippo=3
local pluto=4
end
func()
print(pippo,pluto)
stamperà 3,2, perché il valore di ‘pippo’ è stato sovrascritto dentro la funzione, in quanto ogni variabile non dichiarata esplicitamente local ha visibilità globale. Fanno eccezione gli iteratori dei cicli:
i=10
for i=1,3 do
print(i)
end
print(i)
1
2
3
10
in conclusione: nelle funzioni conviene sempre dichiarare le variabili ’local’, a meno che non sappiate esattamente cosa state facendo!
Per i più virtuosi, divertiamoci a scrivere il fattoriale in maniera ricorsiva:
function fattorialeR(n)
if n==0 then return 1
else return n*fattorialeR(n-1)
end
end
Questo tipo di ricorsione (tail recursion) è implementata in maniera efficiente in Lua, in quanto il compilatore provvede ad ottimizzare le chiamate in modo da non utilizzare spazio nello stack.
Una funzione è anche un tipo di dato, ovvero è possibile ottenere riferimenti a funzioni e utilizzarli associandoli a variabili. Potremmo scrivere ad esempio:
func=fattoriale
if recurse then func=fattorialeR
print(func(10))
che utilizza la versione ricorsiva o iterativa a seconda di una scelta operata in precedenza. Come conseguenza, possiamo scrivere funzioni che ritornano funzioni:
function makeIncr(x)
local i=x
return function()
i=i+1
return i
end
end
dieci=makeIncr(10)
cento=makeIncr(100)
for i=1,5 do
print(dieci(),cento())
end
Non è necessario capire immediatamente l’utilità di costrutti avanzati come questo… Basti dire che sono la base della programmazione funzionale e del concetto di coroutine in Lua. Notiamo infatti che ciascuna delle due funzioni ‘mantiene’ il proprio stato (in questo caso il contatore) indipendentemente, pur essendo generate dalla stessa ‘madre’.