Translate

martes, 10 de mayo de 2022

Currying en Kotlin


Ya hable un monton de currying y no tengo ganas de explicarlo de nuevo, pero ahí va :

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.

Como puedo hacer esto en kotlin? la respuesta es kotlin no soporta currying. Y ya esta :( 

Pero aún podemos crear una función de argumento único que devuelva otra función de argumento único.

Por ejemplo : 

val curriedAdd: (Int) -> (Int) -> Int = { x -> { y -> x + y } }

val add2 : (Int) -> Int = curriedAdd(2)

println(add2(3)) //imprime 5

Como vemos, la primera invocación de curriedAdd devuelve otra función con un parámetro. Lo que hicimos arriba se llama aplicación parcial. Aplicamos solo el primer argumento y preparamos la función para aplicar el segundo.

Eso es básicamente lo que queríamos lograr. Nuestro código puede ser puro, funcional y fácil de probar.

Además, Kotlin no admite curry tal como es. No podemos aplicar solo un argumento a cualquier función. Tenemos que hacer la función con aplicaciones parciales. Pero escribir todas las lambdas como una secuencia de lambdas puede ser molesto.

Y esto es lo que la comunidad hizo por nosotros: una gran biblioteca funcional para Kotlin: funKTionale. El módulo donde viene curry y uncurry es funktionale-currying.

Volviendo a nuestro problema: ¿cómo crear funciones add3, add5, add100 sin generar una gran cantidad de código repetitivo?

Primero, agregue la biblioteca a su script de compilación. En mi caso es gradle:

implementation "org.funktionale:funktionale-currying:1.2"

Y luego podemos hacer : 

val add = { x: Int, y: Int -> x + y}.curried() 

val add3 = add(3)

val add5 = add(5)

val add100 = add(100)

println(add3(3)) // 6

println(add100(-10)) // 90