segue dalla sesta parte
Iteratori e lua funzionale
Cos’è un iteratore? Informaticamente parlando, è un costrutto che ci permette di scorrere strutture dati come liste, array, elenchi. In pratica, dato un elemento della struttura il compito dell’iteratore è farci avere il prossimo su cui operare. Non ci stupirà apprendere che in Lua gli iteratori sono funzioni. Vediamo un semplice esempio:
function reverse_iter(t)
local i=#t+1
return function()
i=i-1
if i>=0 then return t[i] end
end
end
reverse_iter è una fabbrica (factory) di funzioni: ogni volta che la chiamiamo, ci crea una nuova closure, ossia l’iteratore specifico per l’array che gli passiamo. La funzione che otteniamo mantiene il suo stato grazie alle variabili i e t ; quando non ci sono più elementi, restituisce nil. L’iteratore si potrebbe usare così:
lista={10,20,30,40}
iteratore = reverse_iter(lista)
> print(iteratore())
40
> print(iteratore())
30
> print(iteratore())
20
> print(iteratore())
10
> print(iteratore())
nil
oppure, semplificando:
lista={10,20,30,40}
for item in reverse_iter(lista) do
print(item)
end
la semplicità del costrutto for ci nasconde parecchie operazioni: invocare la factory, tenerci un riferimento all’iteratore, chiamarlo ad ogni ciclo e fermare il loop quando otteniamo un valore nil. La flessibilità di Lua ci consente di scrivere lo stesso ciclo in modo alternativo: anziché passare l’array alla funzione, passiamo la funzione come parametro:
lista={5,6,7,8,9}
function alrovescio(f)
for i=5,1,-1 do f(lista[i]) end
end
e quindi stampare tutti gli elementi con:
alrovescio(print)
ma anche fare qualcos’altro, per esempio filtrare i valori pari:
alrovescio(function(x)
if (x%2)>0 then print(x) end
end)
l’uso di questo stile di programmazione è tipico dei linguaggi funzionali, ma come abbiamo visto è semplice utilizzare lo stesso paradigma in Lua. Qualcuno si è perfino divertito a creare un interprete Lisp : http://urn-lang.com/