Funciones De Orden Superior En Kotlin

En este tutorial aprenderás sobre la declaración de funciones de orden superior en Kotlin. Verás ejemplos para pasar una función como argumento de otra y para retornar una función de otra función.

Función De Orden Superior

Una función de orden superior, es una función que puede recibir como argumento una o más funciones y/o retornar una función como resultado.

// Pasar función como argumento de otra función
fun recibirFuncion(parametro1: (String) -> Int, parametro2: Double) {
    // Invocar instancia del tipo función
    val numero: Int = parametro1("Arg")
    
    print(numero)
}

// Retornar función desde otra función
fun retornarFuncion(parametro1: Int): () -> Unit {
    // el retorno es una función lambda
    return { println(parametro1) }
}

Esto es posible gracias a los tipos función que Kotlin incluye en su gramática.

Tomar Funciones Como Argumentos

Para recibir argumentos en una función, agrega a la firma uno o varios parámetros de tipo función.

El fin es ejecutar la función entrante, realizarle una llamada y hacer el uso correspondiente de su resultado.

Por ejemplo:

Supongamos que estamos generando el código para un juego de cartas roguelike y necesitamos poner en juego una carta que causa un efecto, basado en el costo de otra aleatoria en el mazo.

// Función de orden superior
fun playEffectCard(cardCost1: Int, cardCost2: Int, onSuccess: () -> Unit) {
    if (cardCost1 > cardCost2) {
        onSuccess()
    } else {
        println("Sin efectos")
    }
}

fun main() {
    val warriorCardCost = 1
    val randomDeckCardCost = 4
    playEffectCard(warriorCardCost, randomDeckCardCost) { print("Aumentar armadura por 10") }
}

Salida:

Sin efectos

En el código anterior creamos una función de orden superior, que recibe los costos (cardCost1 y cardCost2) de las cartas que serán comparados.

El tercer parámetro onSuccess es una función de tipo () -> Unit, que ejecutará el efecto de la carta, si la comparación fue exitosa.

Al llamar a playEffectCard() en main(), pasamos en el tercer argumento un lambda que imprime el efecto causado.

Debido a que warriorCostCard no es mayor a randomDeckCost, la salida será la no aplicación de efectos.

Pasar Referencia De Función

La función lambda que pasamos como argumento en la función de orden superior anterior, puede ser reescrito como una referencia de función si así lo deseas:

fun increaseArmor() {
    print("Aumentar armadura por 10")
}

fun main() {
    val warriorCardCost = 1
    val randomDeckCardCost = 4
    playEffectCard(warriorCardCost, randomDeckCardCost, ::increaseArmor)
}

Retornar Funciones Desde Funciones

Retornar un tipo función desde una función de orden superior tiene la misma sintaxis de un retorno regular.

Defines el tipo en la firma de la función y en el bloque de código de la misma, usas la expresión return para especificar el literal de función o referencia que será devuelto como valor.

Por ejemplo:

Convertir de metros a centímetros, pulgadas, pies y yardas.

import Dimension.*

enum class Dimension {
    CM, INCH, FOOT, YARD
}

fun getConversion(dimension: Dimension): (Double) -> Double {
    return when (dimension) {
        CM -> { mts -> mts * 100 }
        INCH -> { mts -> mts * 39.37 }
        FOOT -> { mts -> mts * 3.281 }
        YARD -> { mts -> mts * 1.094 }
    }
}

fun main() {
    val meters = 20.0
    print(getConversion(FOOT)(meters))
}

Salida:

65.62

Solución:

El código propuesto provee una clase enum para determinar los tipos de dimensiones que deseamos (CM, INCH, FOOT y YARD).

Luego creamos una función de orden superior que recibe una instancia de Dimension y basado en ella usamos una expresión when para procesar cada constante.

Cada constante arroja como valor una función lambda del tipo (Double)->Double. Lo que significa que toma como parámetro la cantidad en metros y lo mapea a una multiplicación por el factor asociado al sistema de conversión.

Finalmente en main(), declaramos una variable con 20 metros. Luego llamamos a la función getConversion(), especificando que queremos convertir a pies la cantidad.

Como el retorno es una función, al final de los paréntesis podemos añadir otros paréntesis para llamar al cálculo.

Únete Al Discord De Develou

Si tienes problemas con el código de este tutorial, preguntas, recomendaciones o solo deseas discutir sobre desarrollo Android conmigo y otros desarrolladores, únete a la comunidad de Discord de Develou y siéntete libre de participar como gustes. ¡Te espero!