Intro

Para contarles que es Curry me voy a basar en el libro   “JavaScript Patterns – Stoyan Stefanov“. ( Lo pueden comprar en su librería de confianza 😉 )

En este link tienen una def un poco más genérica, desatada del mundo JS.

“Curry es una técnica de transformación de funciones que permite obtener a partir de una función A otra B que es la versión parcialmente aplicada de A.” Después de la teoría vienen un par de formas de hacerlo con JavaScript.

Que es una aplicación y una aplicación parcial?

Podemos tomar con fines prácticos hablando en un contexto menos matemático y mas JS que una aplicación es como una llamada a función y que aplicar parcialmente una función es llamarla con no todos los argumentos esperados sino con algunos de los primeros. Como de esta forma no podemos obtener el resultado final que obtendríamos de pasarle todos los parámetros, lo que se obtiene es una función que se puede llamar con los parámetros restantes y devolver el resultado como si hubiese sido llamada con todos los parámetros.

Implementaciones

Curry manual:

function sumar( x, y ) {
    if ( typeof y === 'undefined' ) { //detección de aplicación parcial
        return function ( y ) { //la transformación ( curring )
            return x + y;
        };
    } else {
        return x + y;//aplicación completa
    }
}

var sumaParcial = sumar( 4 );// Obtener suma parcialmente aplicada, memoriza x

var result = sumaParcial( 5 ); // uso de la versión parcialmente aplicada, el 5 se usa para y que al sumarle la x memorizada ( 4 ) dará como resultado 9. 

//También lo podemos usar así:
var result2 = sumar( 4 ) ( 5 );

En esta implementación del curry, la aplicación parcial está en la misma función sumar, si vamos a usar mucho esta técnica, se puede hacer una forma más versátil que pueda aplicar curry a cualquier función que querramos en el libro aparece el ejemplo, la función schonfinkelize de 7 lineas que le pone curry a lo que se le cruce:

Curry pro

function schonfinkelize(fn) {
   var slice = Array.prototype.slice,
     stored_args = slice.call(arguments, 1);
   return function () {
      var new_args = slice.call(arguments),
         args = stored_args.concat(new_args);
      return fn.apply(null, args);
   };
}

//Ejemplo de uso:
// Función a modificar:
function echo( x ) {
  return x;
}

// Función modificada
var elephantFunction = schonfinkelize( echo, 'algo para recordar' );//La Transformación ( curring )

// Aplicación, en un objeto mock, o un objeto que necesita tener un método que devuelva siempre el mismo valor con fines de polimorfimo
var mock = {
   getMessage: elephantFunction
}

Mas info sobre apply en Patrones de Invocación de Funciones: this y en Modificando el contexto: call, apply y bind

Implementación de Underscore.js

Underscore viene con** la función partial** que permite hacer las partial applications, el ejemplo anterior, hecho con esta funcionalidad de underscore sería :

var mock = {
   getMessage: _.partial( echo, 'algo para recordar' ) //La transformación ( curring )
}

Ejemplos de Uso:

Imagínense que tenemos una función densidad de tres variables de entrada ( x, y , z ) que nos devuelve la concentración de algo ( un compuesto por ejemplo ) en un cuerpo dado. Densidad podría tener información de una tomografía computada o de un examen de resonancia magnética nuclear, x podría representar la dimensión longitudinal de pies a cabeza, y con _.partial( densidad, 3 ), podríamos obtener un corte ( una imagen ) de esa información a 3 centímetros de la planta de los pies.

Ok, que pasa si se nos fué la mano con el fernet y queremos cortes que no sean perpendiculares a ninguno de los ejes xyz? Rta, tendríamos que aplicar un poco (bastante) de matemática, como para obtener una función similar partial, pero que se llame por ejemplo slice que reciba como entrada un vector con un punto por donde debe pasar el corte y otro perpendicular al plano de corte, ejemplo:  corte = _.slice( [3, 0, 0], [0, 0, 1], densidad ) // el corte pasa por x = 3 y el vector normal es el que tiene solo componente z.   La función devuelta tendría dos variables de entrada, que serían coordenadas x y y en el plano de corte ( que no necesariamente son las mismas que las originales).

Bueno, espero que les haya gustado.