Olá pessoal, este é um post sobre Clojure apply e partial functions. Devo confessar que não pesquisei como colegas de clojure tem explicado estas funções. E tenho certeza que existe uma forma melhor de explicá-las mesmo usando JavaScript, mas vale nota que esta explicação foi usada pra ajudar um iniciante no mundo funcional.
Estes trechos de js eu usei ao explicar a um colega no trabalho. E até que serviu pra ilustrar ambos os casos.
Apply
Para um iniciante não é tão fácil entender onde eles irão achar uma oportunidade para usar a função apply. Esta é uma função que normalmente imagina-se que vai passar muito tempo até que ela se torne útil no código dele. Ledo engano!
Depois de ouvir algumas considerações no meu colega newbie, cheguei aos seguintes snippets em Java Script, que ao menos é uma linguagem bem conhecia e então ajudaria na explicação:
// Imagine uma função retornando isto var pessoa = [21, "paulo", "red"]; // E com este resultado, voce tem a seguinte função para invocar var printer = function(age, name, color) { console.log("Person with name " + name + " and age " + age + " and cor " + color); }; // Você provavelmente faria isto printer(pessoa[0], pessoa[1], "vermelho"); // => Person with name paulo and age 21 and cor red // Agora imagine que você pudesse fazer isto: apply(printer, pessoa); // Isto seria possíel se você usasse apply var apply = function(fn, args) { var str = "fn("; for (x = 0; x < args.length; x++) { str = str + "args["+x+"]"; if (x < args.length - 1) { str += ","; } } str += ");"; console.log(str); eval(str); }; // Mesma saída: // => Person with name paulo and age 21 and cor red
Depois de ler este pequeno trecho, ele entendeu instantaneamente tudo e quão útil apply pode ser. Resumindo …
Eu disse a ele: Use apply para funções com número de argumento variável. Funções que você não sabe quantos argumentos ela recebe e você quer considerar cada elemento em um dado vetor como se fossem argumentos independentes de uma função. Ou, mesmo que você conheça a quantidade destes argumentos, por muitas vezes vetores terão exatamente elementos que batem com os argumentos de uma função”.
Para o segundo caso (aí em cima) seria mais fácil usar destructuring, mas ainda assim se aplica.
Partial
Acredite em mim, existem muitas formas de explicar isso. De forma mais científica ou mais simplista. Eu diria que esta forma aqui está mais para simplista. Mas é o suficiente para fazer você começar usar partial.
var hello = function(saud, name) { console.log(saud + ", " + name); }; hello("ola", "brunolandia"); var morning = function(nome) { hello("Bom dia", nome); }; morning("Brunovisk");
Logo depois de ler este snippet
ele logo concluiu: “mas Paulo, morning está basicamente reduzindo a quantidade de argumentos de hello, e então expondo uma segunda função que recebe um argumento, repassando ele para hello, além de passar um segundo argumento prefixado”.
YES. That is it! Mas a questão mais importante que ele fez após seu comentário foi: Quando devo usar isso?
Partial functions tem uma série de aplicações. Para não tornar a coisa científica, vamos ver esta explicação simplista:
Imagine que você está provendo funções para outros desenvolvedores executarem consulta em um banco de dados. Você provavelmente irá criar uma função base, que recebe como argumento uma quantidade enorme de parâmetros para montar a query. E você quer garantir que certos argumentos estejam presentes (campos/constraints/indices).
Uma sábia opção é aplicar sua função base parcialmente com argumentos conhecidos e seguros a respeito da query. Então você pode expor estas novas funções mais seguras e performáticas a outros desenvolvedores.
Existem muito mais casos de uso para partial functions. Uma boa motivação é que usando funções parciais você eleva a legibilidade e elegância do seu código. Veja este excelente post by Christopher Maier bem aqui e tire boas lições.
Bom, espero que tenham gostado e que tenha sido útil para acelerar seu aprendizado. Até a próxima!