De um ponto de vista prático, combinadores são tipos de construções de programação que permitem reunir peças de lógica de maneiras interessantes e geralmente avançadas. Normalmente, usá-los depende da possibilidade de poder empacotar código executável em objetos, geralmente chamados (por razões históricas) de funções lambda ou expressões lambda, mas sua milhagem pode variar.
Um exemplo simples de um combinador (útil) é aquele que recebe duas funções lambda sem parâmetros e cria um novo que as executa em sequência. O combinador real parece no pseudocódigo genérico assim:
func in_sequence(first, second):
lambda ():
first()
second()
O crucial que torna isso um combinador é a função anônima (função lambda) na segunda linha; quando Você ligar
a = in_sequence(f, g)
o objeto resultante a não é o resultado da execução de primeiro f () e depois g (), mas é um objeto que você pode chamar posteriormente para executar f () e g () em sequência:
a() // a is a callable object, i.e. a function without parameters
Da mesma forma, você pode ter um combinador que executa dois blocos de código em paralelo:
func in_parallel(first, second):
lambda ():
t1 = start_thread(first)
t2 = start_thread(second)
wait(t1)
wait(t2)
E então novamente,
a = in_parallel(f, g)
a()
O legal é que 'in_parallel' e 'in_sequence' são ambos combinadores com o mesmo tipo / assinatura, ou seja, ambos pegam dois objetos de função sem parâmetros e retornam um novo. Você pode escrever coisas como
a = in_sequence(in_parallel(f, g), in_parallel(h, i))
e funciona como esperado.
Basicamente, os combinadores permitem construir o fluxo de controle do seu programa (entre outras coisas) de maneira processual e flexível. Por exemplo, se você usar o combinador in_parallel (..) para executar o paralelismo no seu programa, poderá adicionar depuração relacionada a isso à implementação do combinador in_parallel. Posteriormente, se você suspeitar que seu programa possui um bug relacionado ao paralelismo, na verdade você pode apenas reimplementar o in_parallel:
in_parallel(first, second):
in_sequence(first, second)
e com um toque, todas as seções paralelas foram convertidas em seqüenciais!
Os combinadores são muito úteis quando usados corretamente.
O combinador Y, no entanto, não é necessário na vida real. É um combinador que permite criar funções auto-recursivas e você pode criá-las facilmente em qualquer idioma moderno sem o combinador Y.