Algumas correções
Essa função faz com que o computador guarde na memória a variável soma, a variável squared e os respectivos valores. Esses são chamados efeitos colaterais.
Nop, essa não é a definição de efeito colateral. São apenas variáveis (estado) mesmo, só isso. Efeito colateral é quando uma função altera um estado fora de seu escopo. Por exemplo ao alterar uma variável global, um objeto passado por referência, memória apontada por um ponteiro passado como argumento para a função, o conteúdo de um arquivo etc.
Se essas variáveis aí são locais e, por consequência disso, só podem ser acessadas dentro da própria função, então não há efeito colatoral em alterar o valor delas. Se a ideia do exemplo era dizer que as variáveis são globais, então faltou esclarecer isso e explicar direito o conceito.
Agora vamos transformar o mesmo código para programação funcional.
Por que você acha que simplesmente remover as variáveis mudou magicamente de "imperativo" para "funcional"? As duas funções de exemplo que você deu poderiam muito bem serem usadas em paradigma imperativo ou funcional, uma coisa não tem nada a ver com a outra. Você trocou 6 por meia dúzia aí.
O paradigma funcional diz respeito a maneira que você escreve o código do programa e não o código de uma função específica. Mesmo que um programa escrito em paradigma funcional tivesse uma função com efeitos colaterais, isso não faria com que automagicamente o programa deixase de ter sido feito em paradigma funcional.
Do mesmo jeito jeito que o código seguindo Programação Orientada a Objetos (POO), por ter um ou outro código seguindo o paradigma procedural, não deixa de ser um programa em POO.
E seguindo essa linha, também criar uma classe e implementar uns métodos nela não faz com que seu código seja POO. Você pode muito bem estar escrevendo código procedural usando classes (o que ocorre com muita frequência, vale dizer).
Note-se que retiramos as variáveis e fizemos todas as operações no próprio return. Essa mudança elimina os efeitos colaterais que falamos antes , ou seja, nesse caso não estamos mais ocupando espaço na memória para fazer essa operação.
Não existe garantia nenhuma de que o código gerado não precisará de acessos à memória. Isso depende da convenção de chamada e do que o compilador vai fazer para gerar o código dessa função.
Uma função é chamada de pura quando, se invocada mais de uma vez com os mesmos parâmetros, produz exatamente o mesmo resultado.
Além disso, é necessário que ela não cause efeitos colaterais externos como imprimir linha de saída, alterar algo no banco, guardar algo na memória, etc.
Guardar algo na memória principal não faz com que a função deixe de ser pura. Usar a memória é simplesmente inevitável para qualquer software, escrito em qualquer linguagem e em qualquer paradigma. O processador não tem registradores suficientes para que seja possível evitar usar a memória. E mesmo que tivesse há objetos que são grandes demais para ficarem em um registrador (como arrays, listas, estruturas etc.) e há operações em que isso é simplesmente inevitável. Além de estruturas como a hardware stack que, obviamente, fica na memória.
Em outras palavras, mesmo linguagens puramente funcionais como Haskell irão "guardar algo na memória".
Com esses conceitos em mente, podemos fazer composições de funções, tornando nossas operações mais complexas. Pode parecer algo diferente, mas você já pode ter visto em diversas situações.
Em suma, isso significa criar uma nova função por meio da composição de outras.
No exemplo seguinte temos uma função que filtra um array retirando apenas os números pares e, por fim, multiplicando por 2.
Não é isso que significa composição de função e o exemplo dado não é composição de função. "Compor função" é bem mais simples do que isso. É simplesmente passar o retorno de uma função como argumento para outra. Tipo isso:
const result = square(sum(x, y));
Ou então você pode declarar uma nova função fazendo a composição de outras funções. Assim:
function squared_sum(x, y) {
return square(sum(x, y));
}
Veja que eu passo o retorno da função sum
como argumento para a função square
, que por sua vez é o retorno da função squared_sum
. Isso é composição de função. Simples assim.
Dicas
- Qualquer material que tenha "for dummies" ou "para leigos" no título é uma péssima referência. Quando o autor do conteúdo coloca isso no título, 99% das vezes é porque ele mesmo é leigo no assunto mas decidiu falar à respeito porque sim.
- Programação funcional é baseada em lambda calculus. Estude como esse treco funciona que tu vai entender o cerne de FP.
- Sugiro aprender uma linguagem puramente funcional como Haskell, mesmo que não vá de fato programar nela "para valer". Se não as chances são enormes de que você escrever código procedural achando que é funcional, só porque decorou o nome de alguns conceitos de FP
- Toda vez que tu ver um conceito que tu não conhece jogue ele no Google, consulte o artigo na Wikipédia (e as referências), veja vários artigos diferentes, vários vídeos diferentes, várias discussões sobre o assunto em fóruns/blogs/stack overflow etc. Não confie no que uma pessoa em um artigo tem a dizer sobre o assunto.