Encadeamento de função é o pattern onde um grupo de funções é encadeado.
Em uma cadeia, sempre a saída de uma função é a entrada da seguinte, o parâmetro inicial é fornecido à primeira função da cadeia, que segue executando as funções, e o resultado da última função é retornado como resultado da cadeia.
Vejamos como criar cadeia.
Em uma cadeia, sempre a saída de uma função é a entrada da seguinte, o parâmetro inicial é fornecido à primeira função da cadeia, que segue executando as funções, e o resultado da última função é retornado como resultado da cadeia.
Vejamos como criar cadeia.
Python
A forma mais simples simples de encadear funções é simplesmente efetuar a chamada, como o código Python a seguir:
f1 = lambda x: x * 2
f2 = lambda x: x - 1
f3 = lambda x: x // 3
print(f3(f2(f1(8))))
Porém esse código é visualmente confuso e difícil de ser depurado. É conveniente criar uma fábrica (factory) de cadeias:
chain = lambda *funcs: \
reduce(lambda acc, func: (lambda x: func(acc(x))),
funcs or [lambda x: x])
the_chain = chain(
lambda x: x * 2,
lambda x: x - 1,
lambda x: x // 3,
)
print(the_chain(8))
Repare que as funções agora estão na ordem em que são executadas:
- O número é dobrado;
- O resultado da primeira função é decrementado;
- O resultado da terceira função é triplicado e retornado.
A função
O segundo parâmetro de
Com este procedimento, é possível reduzir a lista de funções a uma função representando o encadeamento das funções fornecidas.
reduce()
de Python executa a redução de um map/reduce: o primeiro parâmetro é uma função que recebe o acumulador e o próximo valor, retornando o resultado parcial.O segundo parâmetro de
reduce()
é a lista a ser reduzida, no caso, a lista de funções ou, caso nenhuma função tenha sido informada, um função vazia que retorna o próprio parâmetro fornecido.Com este procedimento, é possível reduzir a lista de funções a uma função representando o encadeamento das funções fornecidas.
Erlang
Em Erlang as coisas também podem ser interessantes.
Criaremos duas funções, uma fábrica a ser exportado (
Criaremos duas funções, uma fábrica a ser exportado (
chain/1
) e uma função de redução (chain/2
) que não deve ser exportada:
-module(chain).
-export([chain/1]).
chain(Funs) when is_list(Funs) ->
chain(Funs, fun(X) -> X).
chain([], Acc) -> Acc;
chain([Fun|Rest], Acc) when is_function(Fun) ->
chain(Rest, fun(X) -> Fun(Acc(X)) end).
Você pode então executar no shell:
1> c(chain).
{ok,chain}
2> Fun = chain:chain([
2> fun(X) -> X * 2 end,
2> fun(X) -> X - 1 end,
2> fun(X) -> X div 3 end
2> ]).
#Fun<chain.1.134034448>
3> Fun(8).
5
4>
Haskell
Haskell por outro lado já possui uma fábrica de cadeias, usando o carácter
Então, por exemplo:
Crie um módulo:
$
, infelizmente na ordem inversa: primeiro as últimas funções a serem executadas, e por último as primeiras.Então, por exemplo:
f1 $ f2 $ f3 x
é executado como f1 (f2 (f3 x))
.Crie um módulo:
module Chain where
the_chain :: Int -> Int
the_chain n = (`div` 3) $ (\x -> x - 1) $ (* 2) n
No prompt do
ghci
execute:
Prelude> :load chain.hs
[1 of 1] Compiling Chain ( chain.hs, interpreted )
Ok, modules loaded: Chain.
*Chain> the_chain 8
5
*Chain>
[]’s
Cacilhας, La Batalema