Queste funzioni “*”
(Strip from http://xkcd.com/)
Che cosa significa la “*” in rember* e insertR*? In generale, data una funzione f, in programmazione funzionale f* significa applicare f uniformemente a una struttura. Se la struttura è una lista, f* restituisce una lista con tutti gli elementi trasformati da f. Se la struttura è un albero, il risultato sarà un albero.
Quindi la rember* non è altro che la reject applicata ad alberi (ovvero liste comunque innestate. Sì Ugo, alla fine queste liste sono piante :-).
Il prossimo passo è generalizzare: definire una funzione star come fattor comune di insertR* e rember*, in modo da poter scrivere
def rember_star(a, l)
star l, lambda { |sym| sym == a ? [] : [sym] }
end
def insertR_star(old, new, l)
star l, lambda { |sym| sym == old ? [old, new] : [sym] }
end
La funzione star prende una lista e una funzione; dunque è una funzione di ordine superiore. Cool stuff! La mia soluzione:
def star(l, f)
if l.is_a? Symbol
l
elsif l.empty?
[]
else
f.call(star(l.first, f)) + star(l.rest, f)
end
end
Espresse così la rember* e la insertR* mi sembrano più chiare. La star esprime lo schema ricorsivo, le lambda descrivono cosa fare localmente.
Prossimo esercizio: risolvere in Ruby i problemi posti dal genio di Lists and Lists (Gordon Plotkin, 1996).
Vedi anche: Why Ruby is an acceptable LISP
