Pular para o conteúdo principal

Curry with JS

Partial application and currying with Javascript

In the strict way, currying is the technique of transforming a function that takes multiple arguments (a tuple of arguments) to one function that receive only one. In such way, currying techniques allow transform one multi-parameter function in a chain of functions, each one with a single argument. Looks complicated? Blah.. it is not true.
In this little article, we are actually more interesting in partial applications. Let’s take the Mozilla Example for replace function in String. As we know, we can use a “replacer” function as paramenter for replace method in String object.
Let’s say that we want to split a String defined by a non-numerical part, a numerical part and finally a non-alphanumeric part. Here is how:
function replacer(match, p1, p2, p3, offset, string){
  // p1 is nondigits, p2 digits, and p3 non-alphanumerics
  return [p1, p2, p3].join(' - ');
};
We can try it as usual…
var newString = "abc12345#$*%".replace(/([^\d]*)(\d*)([^\w]*)/, replacer);
So far so good. Let’s say now that the delimiter should change according with some conditions, e.g. locale specific.
function replacer(delimiter, match, p1, p2, p3, offset, string){
  return [p1, p2, p3].join(delimiter);
}
That’s bad. We cannot apply that replacer in regexp replace function. What can you do?
We want to have a partial application for that function. Take that!
function makeReplacer(delimiter) {
    return function replacer(match, p1, p2, p3, offset, string){
      return [p1, p2, p3].join(delimiter);
    }
}
So now, we can create a replacer for comma-separated-value:
var delimiter = ',';
var csvReplacer = makeReplacer(delimiter)
That constructor is so simple, so elementar that we could create a generic way to do that. Let’s create a curry function.
Function.prototype.curry = function() {
    var fn = this, args = Array.prototype.slice.call(arguments);
    return function() { // new function
      return fn.apply(this, args.concat(
        Array.prototype.slice.call(arguments)));
    };
  };
How does the magic work? Closure!!! That dammit word is what defined the whole magic.
var fn = this;
var args = Array.prototype.slice.call(arguments);
First, arguments is a special object to access the parameters. However, arguments type is very similar to Array but it is not an Array. To use it in apply method we need to convert it to real Array. For that, we gonna use slice function. But slice function is a method defined on Array. Ok. Ok. Let’s use the slice function from Array replacing “this” object (within slice context) by “arguments” object. with the mighty call method…
Array.prototype.slice.call(arguments);
In that way, we have this and arguments saved on context. The Closure magic will keep that context (those local variables fn and args) within the context of new function. In that new function context, we also have a new values for this variable (now keeping the new function reference) and arguments (now the arguments of that function). So we can concat (add all elements) from arguments the to our args and we gonna have all arguments necessary for the original function.
return fn.apply(this, args.concat(Array.prototype.slice.call(arguments)));};
So here we can rewrite the makeReplacer with curry… (because it is more spicy):
var delimiter = ',';
   var csvReplacer = replacer.curry(delimiter)

Comentários

Postagens mais visitadas deste blog

Expressões, preconceito e racismo

Expressões preconceituosas e racistas Antes de alguma outra frase, primeiro peço licença para falar de mais um assunto do qual não domino. Falo por acreditar que um leigo presta serviço maior ao debater assunto com base em fontes (ainda que seja uma Wikipedia) e no pensamento lógico do que simplesmente se manter mudo a questões do cotidiano. Em voga agora está em falar quais são ou eram as expressões preconceituosas e racistas que até a pouco eram toleradas em muitos meios.
Como é covarde dizer que em boca fechada não entra racismo. O racismo não é perpetrado apenas por quem profere mas por quem se cala à agressão perpetrada a outrem. Mas veremos que a questão é muito mais complexa que os cães raivosos do politicamente correto querem dizer.
Tomo aqui a palavra racista, como sendo algo usado para impor a dominação de uma “raça” sobre outra. Portanto, a acusação de racismo vai muito além da mera acusação de preconceito. Não tenho o menor apreso por vitimismo barato, onde expressões que…

Um texto pós-moderno - better man

Espere olhando para as horas... são 4 horas. Tem que parar. Nesse tom melancólico, começa a modesta música "better man", uma balada pop composta por Eddie Vedder ainda na adolescência. A música é a ilustração perfeita da ironia. O próprio título é irônico, uma vez que em momento algum na música aparece um better man.

She lies and says she's in love with him, can't find a better man...

Irônico, não!? Para começar, com a personagem central da história, a mulher que aguarda tarde da noite seu esposo... Ela chega a treinar com o espelho o fim do relacionamento. E o que faz? Diz a negação do que queria dizer.

Vedder escreve músicas sobre sentimentos fortes. Sua relação com a mãe foi bastante complicada pelo o que descreve em suas canções. Na trilogia Mommy, Vedder descreve um homem perturbado com o relacionamento materno; a mãe mente para o filho sobre a identidade do pai, revela a verdade para o garoto na puberdade dizendo a ele como se parece com o verdadeiro pai e o leva …

Filme: Obrigado Por Fumar

Obrigado Por Fumar (Thank you for Smoking) - 2006Filme escrito e dirigido por Jason Reitman, produzido por David Sacks e baseado na novela de Christopher Buckley. Duração de 92 minutos.
"Obrigado Por Fumar" é um aclamado filme, vencedor do globo de ouro 2006 e sucesso em bilheterias (com faturamento superior a 39 milhões de dólares). O filme conta a história de Nick Naylor (Aaron Eckhart), vice-presidente da empresa Academia do Estudo do Tabaco, um lobby da indústria tabagista, e como ele usa suas habilidades de persuação para defender os interesses de seus superiores.
Direção muito interessante: ao contrário do que se pode esperar, o filme não mostra um quadro contaminado por fumaça em que o próprio telespectador tenha dificuldades em respirar. Aliás, o filme não mostra nehuma pessoa fumando. Também não faz uma crítica raivosa à indústria do cigarro. Seus argumentos são sutis, inteligentes e bem-humorados. Mas, a mensagem não passa despercebida pelo público, apenas não o agri…