Programação funcional em JavaScript Parte 2 - Combinadores
Pawel Ged
Programador Vue.js
Esta é a segunda parte de nossa série de artigos dedicados ao poder da programação funcional no JavaScript. Confira este artigo para expandir seus conhecimentos sobre Combinadores.
Introdução aos Combinadores
Os combinadores são funções de nível superior que permitem combinar funções, variáveis ou outros combinadores. Normalmente, não contêm declarações das suas próprias variáveis ou lógica empresarial. São os únicos que permitem descarregar o controlo num programa de funções.
Neste artigo, tentarei abordar alguns deles:
Torneira
Caril
Tubo/Compor
Garfo
Alternância
Sequência
Torneira
Um combinador é muito útil para funções que não devolvem nada. Recebe a função para a qual o parâmetro vai e depois é devolvido.
Declaração
const tap = (fn) => (valor) => {
fn(valor);
retorna o valor;
};
Exemplo imperativo
const [items, setItems] = useState(() => [])
axios
.get('http://localhost')
.then({ data } => {
setItems(data)
console.log(data)
onLoadData(data)
}).then(...) // retorna indefinido - os dados na promessa foram modificados
Exemplo declarativo
const [items, setItems] = useState(() => [])
axios
.get('http://localhost')
.then(({ data }) => data)
.then(tap(setItems)) // (dados) => { setItems(dados); return dados }
.then(tap(console.log)) // um then = uma função = uma responsabilidade
.then(tap(onLoadData))
.then(...) // ainda acesso aos dados originais
// fácil de manter o princípio de abrir/fechar
Caril
Divide os argumentos de uma função e torna possível chamá-los sequencialmente.
const sum = (a, b, c) => a + b + c
const currySum = curry(sum)
/*
chamadas possíveis
currySum(a)(b)(c),
currySum(a)(b,c),
currySum(a,b)(c),
currySum(a,b,c)
*/
currySum(1) // (b, c) => 1 + a + b ou (b) => (c) => 1 + a + b
currySum(5)(10) // (c) => 5 + 10 + b
currySum(5, 10) // (c) => 5 + 10 + b
currySum(5)(10)(20) // 35
currySum(5, 10)(20) // 35
currySum(5)(10, 20) // 35
const divideBy = curry((a, b) => b / a)
const multiplyBy = curry((a, b) => a * b)
const divideByTwo = divideBy(2)
divideByTwo(10) // devolve 5
const multiplyByFive = multiplyBy(5)
multiplyByFive(10) // devolve 50
Tubo/Compor
Através da composição, é possível passar dados de uma função para outra. É importante que as funções recebam o mesmo número de argumentos. A diferença entre pipe e compose é que o primeiro executa a função do primeiro ao último, e o compose chama-as a partir do fim.