Monadi e Python

Sul sito di GenroPy, stiamo discutendo della programmazione ad eventi e della programmazione asincrona. Non abbiamo ancora identificato la tecnica migliore per scrivere il codice.

Con un po’ di fantasia, potremmo scrivere così:

def tbDetail(self, parent, **kwargs):
    tb = parent.toolbar(**kwargs)
    tb.button('New Detail', action=fire('master.save')|fire('detail.record.pkey'))

Per chiarezza, togliamo un po’ di magia dal parametro action:

def tbDetail(self, parent, **kwargs):
    tb = parent.toolbar(**kwargs)
    tb.button('New Detail', action=self.onNewDetail)

def onNewDetail(self, do):
    do | fire('master.save') | fire('detail.record.pkey')

Può sembrare che stia piegando la sintassi di Python per i miei torbidi scopi, in realtà sto facendo ricorso ad un ben noto strumento della programmazione funzionale. In particolare, la struttura dati che viene passata a onNewDetail è una monade.

Si possono scrivere funzioni di ordine superiore, per combinare insieme computazioni e fornire strutture di controllo:

def onNewDetail(self, do):
    do | unless(get('master.saved'), fire('master.save')) | fire('detail.record.pkey')

L’operatore | (bind) modifica la monade (inizialmente vuota, passata nel parametro do), applicando la funzione che lo segue.

Qui uso le monadi a due livelli:

  • nel codice Python, per costruire una semplice AST e generare codice Javascript.
  • nel codice Javascript che verrà generato, per implementare la programmazione asincrona sotto forma di continuation monad basata sulle Promise di Dojo 1.5.