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

Leave a Reply