El currying es una técnica de programación que consiste en transformar una función, que toma varios argumentos, en otras que pueden ser llamadas incluyendo un nuevo argumento. Esto se logra creando una función que toma un argumento y devuelve otra función que toma el siguiente argumento, y así sucesivamente hasta que se han procesado todos los parámetros.
Ejemplos
Para los ejemplos haré uso de Python, aunque es fácilmente portable a otros lenguajes modernos como JavaScript o cualquier lenguaje funcional.
Vamos a crear funciones nuevas, a partir de una plantilla, que multipliquen por un número determinado:
def multiplicar(x, y):
return x * y
def curried_multiplicar(x):
def por(y):
return multiplicar(x, y)
return por
doble = curried_multiplicar(2) # Definimos x. "doble" será la función a invocar, que multiplicará por 2 el nuevo argumento.
triple = curried_multiplicar(3) # Definimos x. "triple" será la función a invocar, que multiplicará por 3 el nuevo argumento.
print(doble(4)) # Definimos y. Imprime 8
print(triple(5)) # Definimos y. Imprime 15
Aquí puedes ver el mismo ejemplo en Elisp, usando un macro para crear la función.
(defun multiplicador (x y)
(* x y))
(defmacro curried-multiplicador (x)
`(lambda (y) (multiplicador ,x y)))
(setq doble (curried-multiplicador 2))
(setq triple (curried-multiplicador 3))
(funcall doble 4) ;; 8
(funcall triple 5) ;; 15
Otro ejemplo, concadenar un símbolo a una cantidad.
def formatear_moneda(simbolo:str, cantidad:float | int) -> str:
cantidad_redondeada = round(cantidad, 2)
cantidad_formateada = str("%.2f" % cantidad_redondeada).replace(".", ",")
return f"{cantidad_formateada} {simbolo}"
def curried_formatear_moneda(simbolo: str):
def formatear(cantidad):
return formatear_moneda(simbolo, cantidad)
return formatear
formatear_euros = curried_formatear_moneda("€")
formatear_dolares = curried_formatear_moneda("$")
print(formatear_euros(123.45)) # "123,45 €"
print(formatear_dolares(678.9)) # "678,90 $"
Pero no creas que estamos limitados con los parámetros. Puedes utilizar todos los argumentos que necesites mientras las funciones estén dentro de la anterior. A continuación puedes ver un ejemplo donde se suman 3 números, siendo la función curried
definida con una x
determinada.
def sumar(x, y, z):
return x + y + z
def curried_sumar(x):
def mas(y):
def y_mas(z):
return sumar(x, y, z)
return y_mas
return mas
suma_tres = curried_sumar(3)
suma_cinco = curried_sumar(5)
print(suma_tres(4)(5)) # 12
print(suma_cinco(6)(7)) # 18
Otro ejemplo podría ser definir una función, llamada aplicar_operacion
que tome el argumento String operacion
(puede admitir valores como “suma”, “resta”, “multiplica” y “divide”). La función debe devolver otra función que tome 2 números y aplique la operación matemática adecuada.
def aplicar_operacion(operacion: str):
def primer_numero(num1: float | int):
def segundo_numero(num2: float | int):
if operacion == "suma":
return num1 + num2
elif operacion == "resta":
return num1 - num2
elif operacion == "multiplicacion":
return num1 * num2
elif operacion == "division":
return num1 / num2
else:
return "Operacion no valida"
sumar = aplicar_operacion("suma")
dividir = aplicar_operacion("divide")
print(sumar(3)(2)) # 5
print(dividir(10)(4)) # 2.5
Conclusión
Entre sus ventajas, me quedaría con su legibilidad. Al utilizar currying puedes crear funciones con nombres más descriptivos que mejorar la legibilidad. Por ejemplo, resulta muy claro que ocurre si utilizo formatear_euros
en lugar de formatear_moneda
. El código se vuelve flexibilidad, podemos crear funciones que puedes ser invocadas de diferentes maneras pero que sus argumentos ya están definidos reutilizando una misma función que nos puede servir como plantilla.
Ya conoces la herramienta, ahora queda en tu poder cuando debes utilizarlo.
{{ comments.length }} comentarios