A importância da programação funcional em JS

Posted by Raphael Lima on 11-10-2016

Este é o segundo post da série sobre Funções JavaScript. Veremos sobre o conceito de callback e programação funcional em JS.

O que são funções de callback?

Entender o conceito de callback é uma parte essencial para o aprendizado do JavaScript Funcional. Callback é o nome dado a funções que são declaradas para serem invocadas por outros códigos posteriormente em um momento apropriado de execução. Para ser mais claro, são as funções que serão “chamadas de volta” (to call back) após uma determinada execução.

Callbacks estão por todas as partes de um código JavaScript, veremos abaixo um exemplo de seu uso.

function test (callback) {
  return callback();
}

Embora este exemplo seja extremamente simples, ele nos ajuda a demonstrar e enteder a capacidade de se transmitir uma função para a outra como argumento e invocá-la de volta.

'use strict'
let text = 'I am a callback'
test ((text) => {
  return text;
})

A idéia destes dois códigos é simples. Invocamos a função test() e passamos uma função (callback) que retorna a string text. Muito simples, não? Pois é, mas isso é devido a natureza funcional do JS que nos permite trabalhar com funções como objetos de primeira classe.

Agora vamos analisar o conceito de callback aplicado em uma linguagem não-funcional.

Trabalhando com um comparador

Sempre quando trabalhamos com coleções dados, é muito provável que em um dado momento teremos que classificá-los de alguma maneira. Suponhamos que temos um array de números aleatórios, linguagens funcionais e não-funcionais como JS e Java, nos fornecem uma forma de ordenar arrays tanto de forma crescente quanto decrescente. Veremos primeiro em Java:

Integer [] numeros = {15, 2, 1, 43, 41, 200, 3, 12};
Arrays.sort(numeros);

Agora em JS:

var numeros = [15, 2, 1, 43, 41, 200, 3, 12]
numeros.sort();

O que podemos de diferença, mesmo que a primeira vista pequena, nos dois códigos é que o Java nos fornece uma classe com uma função estática. Já o JavaScript proporciona a funcionalidade como um método do array. Para vermos as diferenças aumentarem, basta alterarmos a ordem de classificação para decrescente, por exemplo.

Já que em Java não podemos declarar métodos indivudalmente e nem passá-los como argumento para outros métodos, devemos então, declara-los como membros de um objeto. Portanto, o método Arrays.sort() aceita um objeto contendo o método de comparação que será chamado como um callback toda vez que uma comparação tiver de ser feita. Após as devidas alterações, usando uma implementação anônima embutida de Comparator, o código Java para ordenação decrescente ficará assim:

Arrays.sort(numeros, new Comparator<Integer>(){
  public int compare (Integer valor1, Integer valor2) {
    return valor2 - valor1;
  }
});

Através de uma simples subtração o método compare() deve retornar um número negativo caso a ordem dos números estaja invertida, um número positivo caso contrário e zero se os valores forem iguais. Isto faz com que o array seja ordenado em ordem decrescente.

Ok, isto não foi tããão complicado, mas a quantidade de código cresceu e o deixou mais verboso se comparmos a uma mesma implementação feita em JavaScript:

var numeros = [15, 2, 1, 43, 41, 200, 3, 12]
numeros.sort(( valor1, valor2 ) => { return value2 - value1 });

Simples, não? Sem interfaces, objetos adicionais… Apenas 1 linha e só! Isso se dá graças ao JavaScript nos permitir passar uma função anônima como parâmetro diretamente para o método sort() do array.

Obs: A função anônima foi implementada usando arrow function, se você não a conhece visite o ES6 Features.

A importância do JavaScript funcional

O JavaScript nos permite criar funções como uma entidade assim como qualquer objeto, nos permite também passar funções como argumento para métodos assim como objetos. E isso se dá por conta da sua diferença funcional. A capacidade de declarar funções em qualquer ponto do código é uma das características mais importantes do JS mas, independentemente da forma como são declaradas, podemos referencia-las como valores e utiliza-las como blocos fundamentais para libs.

Ter um bom entendimento de como funções funcionam, nos permite melhorar nossa capacidade de escrever bons códigos de forma clara, concisa e principalmente reutilizáveis. Embora a linguagem Java tenha incluído na versão 8 expressões lambda a fim de se ter aspectos funcionais, ela ainda não é uma linguagem funcional. As comparações feitas neste post não foi com o intuito de criticar a linguagem Java e sim comparar uma determinada abordagem entre uma linguagem funcional com uma não-funcional e optei por utilizar Java pois esta é uma linguagem que conheço.

Bom, por hoje é só. Deixem seus comentários e acompanhem os próximos posts. Até!