domingo, 7 de octubre de 2012

Currying


Currying es una técnica de transformación de una función con múltiples argumentos de tal manera que se puede llamar como una cadena de funciones cada uno con un único argumento.

Vamos a explicarlo con un ejemplo, supongamos que tenemos una función f(x,y) para evaluar esta función la llamamos de la siguiente forma f(2,3) por ejemplo. Suponiendo que no tenemos el valor de y se podría definir una función g(y) = f(2,y). De esta forma cuando llamamos a g(3) = f(2,3)

No parece una técnica muy potente, simplemente definimos una función como una segunda función con parámetros fijos, pero esta técnica con clousures puede ser muy útil y nos permite componer funciones a partir de otras.

Oficialmente cada función de Haskell solo puede tomar un parámetro.  Todas las funciones que aceptan más de un parámetro hacen uso de currying. Cuando tenemos una función con dos parámetros en realidad por ejemplo:

max 4 5

es igual que llamar

(max 4) 5

(max 4) es una función que devuelve el parámetro si es mayor a 4 o 4 si es menor.

Por ejemplo en Haskell se puede definir una función double de la siguiente manera:


mult :: Int -> Int -> Int
mult x y = x * y



double = mult 2


En la pagina de scala podemos encontrar el siguiente ejemplo:


object CurryTest extends Application {

  def filter(xs: List[Int], p: Int => Boolean): List[Int] =
    if (xs.isEmpty) xs
    else if (p(xs.head)) xs.head :: filter(xs.tail, p)
    else filter(xs.tail, p)

  def modN(n: Int)(x: Int) = ((x % n) == 0)

  val nums = List(1, 2, 3, 4, 5, 6, 7, 8)
  println(filter(nums, modN(2)))
  println(filter(nums, modN(3)))
}


Noten que la función modN es llamada con un parámetro por lo tanto devuelve una función del tipo Int => Boolean que luego se utiliza en la función filter.

Currying es una técnica que nos facilita la vida y cobra gran potencia junto a el uso de clousures.

Dejo links:
http://www.scala-lang.org/node/135
http://www.engr.uconn.edu/~jeffm/Papers/curry.html
http://blog.gnucom.cc/2010/currying-in-f/
http://www.haskell.org/haskellwiki/Currying
http://en.wikipedia.org/wiki/Currying