Da un punto di vista pratico i combinatori sono tipi di costrutti di programmazione che ti permettono di mettere insieme pezzi di logica in modi interessanti e spesso avanzati. In genere il loro utilizzo dipende dalla possibilità di essere in grado di impacchettare il codice eseguibile in oggetti, spesso chiamati (per ragioni storiche) funzioni lambda o espressioni lambda, ma il chilometraggio può variare.
Un semplice esempio di un (utile) combinatore è quello che accetta due funzioni lambda senza parametri e ne crea una nuova che le esegue in sequenza. L'attuale combinatore si presenta in uno pseudocodice generico come questo:
func in_sequence(first, second):
lambda ():
first()
second()
La cosa cruciale che rende questo un combinatore è la funzione anonima (funzione lambda) sulla seconda riga; quando chiami
a = in_sequence(f, g)
l'oggetto risultante a non è il risultato dell'esecuzione prima di f () e poi g (), ma è un oggetto che è possibile chiamare in seguito per eseguire f () e g () in sequenza:
a() // a is a callable object, i.e. a function without parameters
Allo stesso modo puoi avere un combinatore che esegue due blocchi di codice in parallelo:
func in_parallel(first, second):
lambda ():
t1 = start_thread(first)
t2 = start_thread(second)
wait(t1)
wait(t2)
E poi di nuovo,
a = in_parallel(f, g)
a()
La cosa interessante è che 'in_parallel' e 'in_sequence' sono entrambi combinatori con lo stesso tipo / firma, cioè entrambi prendono due oggetti funzione senza parametri e ne restituiscono uno nuovo. Puoi effettivamente scrivere cose come
a = in_sequence(in_parallel(f, g), in_parallel(h, i))
e funziona come previsto.
Fondamentalmente così i combinatori ti consentono di costruire il flusso di controllo del tuo programma (tra le altre cose) in modo procedurale e flessibile. Ad esempio, se si utilizza il combinatore in_parallel (..) per eseguire il parallelismo nel programma, è possibile aggiungere il debug relativo a quello all'implementazione del combinatore in_parallel stesso. Successivamente, se sospetti che il tuo programma abbia un bug relativo al parallelismo, puoi semplicemente reimplementare in_parallel:
in_parallel(first, second):
in_sequence(first, second)
e con un colpo solo, tutte le sezioni parallele sono state convertite in sequenziali!
I combinatori sono molto utili se usati correttamente.
Il combinatore Y, tuttavia, non è necessario nella vita reale. È un combinatore che ti consente di creare funzioni auto-ricorsive e puoi crearle facilmente in qualsiasi linguaggio moderno senza il combinatore Y.