A煤n no tienes acceso a esta clase

Crea una cuenta y contin煤a viendo este curso

High Order functions

29/37
Recursos

Aportes 11

Preguntas 3

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesi贸n.

Funciones de orden superior

Kotlin es un lenguaje orientado a objetos pero introduce caracter铆sticas existentes en los lenguajes funcionales que nos permiten crear un c贸digo m谩s claro y expresivo.

Una de las caracter铆sticas del paradigma de la programaci贸n funcional son las funciones de orden superior.

Las funciones de orden superior son funciones que pueden recibir como par谩metros otras funciones y/o devolverlas como resultados.

Veremos una serie de ejemplos muy sencillos para ver como Kotlin implementa el concepto de funciones de orden superior y a medida que avancemos en el curso podremos ver las ventajas de este paradigma.

Problema 1
Definir una funci贸n de orden superior llamada operar. Llegan como par谩metro dos enteros y una funci贸n. En el bloque de la funci贸n llamar a la funci贸n que llega como par谩metro y enviar los dos primeros par谩metros.
La funci贸n retorna un entero.

Proyecto147 - Principal.kt

fun operar(v1: Int, v2: Int, fn: (Int, Int) -> Int) : Int {
    return fn(v1, v2)
}

fun sumar(x1: Int, x2: Int) = x1 + x2

fun restar(x1: Int, x2: Int) = x1 - x2

fun multiplicar(x1: Int, x2: Int) = x1 * x2

fun dividir(x1: Int, x2: Int) = x1 / x2

fun main(parametro: Array<String>) {
    val resu1 = operar(10, 5, ::sumar)
    println("La suma de 10 y 5 es $resu1")
    val resu2 = operar(5, 2, ::sumar)
    println("La suma de 5 y 2 es $resu2")
    println("La resta de 100 y 40 es ${operar(100, 40, ::restar)}")
    println("El producto entre 5 y 20 es ${operar(5, 20, ::multiplicar)}")
    println("La divisi贸n entre 10 y 5 es ${operar(10, 5, ::dividir)}")
}

Tenemos definidas 6 funciones en este problema. La 煤nica funci贸n de orden superior es la llamada 鈥渙perar鈥:

fun operar(v1: Int, v2: Int, fn: (Int, Int) -> Int) : Int {
    return fn(v1, v2)
}

El tercer par谩metro de esta funci贸n se llama 鈥渇n鈥 y es de tipo funci贸n. Cuando un par谩metro es de tipo funci贸n debemos indicar los par谩metros que tiene dicha funci贸n (en este caso tiene dos par谩metros enteros) y luego del operador -> el tipo de dato que retorna esta funci贸n:

fn: (Int, Int) -> Int

Cuando tengamos una funci贸n como par谩metro que no retorne dato se indica el tipo Unit, por ejemplo:

fn: (Int, Int) -> Unit

El algoritmo de la funci贸n operar consiste en llamar a la funci贸n fn y pasar los dos enteros que espera dicha funci贸n:

return fn(v1, v2)

Como la funci贸n operar retorna un entero debemos indicar con la palabra clave return que devuelva el dato que retorna la funci贸n 鈥渇n鈥.

Las cuatro funciones que calculan la suma, resta, multiplicaci贸n y divisi贸n no tienen nada nuevo a lo visto en conceptos anteriores:

fun sumar(x1: Int, x2: Int) = x1 + x2

fun restar(x1: Int, x2: Int) = x1 - x2

fun multiplicar(x1: Int, x2: Int) = x1 * x2

fun dividir(x1: Int, x2: Int) = x1 / x2

En la funci贸n main llamamos a la funci贸n operar y le pasamos tres datos, dos enteros y uno con la referencia de una funci贸n:

val resu1 = operar(10, 5, ::sumar)

Como vemos para pasar la referencia de una funci贸n antecedemos el operador ::
La funci贸n operar retorna un entero y lo almacenamos en la variable resu1 que mostramos luego por pantalla:

println("La suma de 10 y 5 es $resu1")

Es importante imaginar el funcionamiento de la funci贸n operar que recibe tres datos y utiliza uno de ellos para llamar a otra funci贸n que retorna un valor y que luego este valor lo retorna operar y llega finalmente a la variable 鈥渞esu1鈥.

Llamamos a operar y le pasamos nuevamente la referencia a la funci贸n sumar:

val resu2 = operar(5, 2, ::sumar)
println("La suma de 5 y 2 es $resu2")

De forma similar llamamos a operar y le pasamos las referencias a las otras funciones:

println("La resta de 100 y 40 es ${operar(100, 40, ::restar)}")
println("El producto entre 5 y 20 es ${operar(5, 20, ::multiplicar)}")
println("La divisi贸n entre 10 y 5 es ${operar(10, 5, ::dividir)}")

Tener en cuenta que para sumar dos enteros es mejor llamar directamente a la funci贸n sumar y pasar los dos enteros, pero el objetivo de este problema es conocer la sintaxis de las funciones de orden superior presentando el problema m谩s sencillo.

Las funciones de orden superior se pueden utilizar perfectamente en los m茅todos de una clase.

Problema 2

Declarar una clase que almacene el nombre y la edad de una persona. Definir un m茅todo que retorne true o false seg煤n si la persona es mayor de edad o no. Esta funci贸n debe recibir como par谩metro una funci贸n que al llamarla pasando la edad de la persona retornara si es mayor o no de edad.
Tener en cuenta que una persona es mayor de edad en Estados Unidos si tiene 21 o m谩s a帽os y en Argentina si tiene 18 o m谩s a帽os.

Proyecto148 - Principal.kt

class Persona(val nombre: String, val edad: Int) {
    fun esMayor(fn:(Int) -> Boolean): Boolean {
        return fn(edad)
    }
}

fun mayorEstadosUnidos(edad: Int): Boolean {
    if (edad >= 21)
        return true
    else
        return false
}

fun mayorArgentina(edad: Int): Boolean {
    if (edad >= 18)
        return true
    else
        return false
}

fun main(parametro: Array<String>) {
    val persona1 = Persona("juan", 18)
    if (persona1.esMayor(::mayorArgentina))
        println("${persona1.nombre} es mayor si vive en Argentina")
    else
        println("${persona1.nombre} no es mayor si vive en Argentina")
    if (persona1.esMayor(::mayorEstadosUnidos))
        println("${persona1.nombre} es mayor si vive en Estados Unidos")
    else
        println("${persona1.nombre} no es mayor si vive en Estados Unidos")
}

Declaramos la clase Persona con dos propiedades llamadas nombre y edad:

class Persona(val nombre: String, val edad: Int) {

La clase persona por si misma no guarda la nacionalidad de la persona, en cambio cuando se pregunta si es mayor de edad se le pasa como referencia una funci贸n que al pasar la edad nos retorna true o false:

fun esMayor(fn:(Int) -> Boolean): Boolean {
        return fn(edad)
    }

Tenemos dos funciones que al pasar una edad nos retornan si es mayor de edad o no:

fun mayorEstadosUnidos(edad: Int): Boolean {
    if (edad >= 21)
        return true
    else
        return false
}

fun mayorArgentina(edad: Int): Boolean {
    if (edad >= 18)
        return true
    else
        return false
}

En la funci贸n main creamos un objeto de la clase persona:

val persona1 = Persona("juan", 18)

Llamamos al m茅todo esMayor del objeto persona1 y le pasamos la referencia de la funci贸n 鈥渕ayorArgentina鈥:

 if (persona1.esMayor(::mayorArgentina))
        println("${persona1.nombre} es mayor si vive en Argentina")
    else
        println("${persona1.nombre} no es mayor si vive en Argentina")

Ahora llamamos al m茅todo esMayor pero pasando la referencia de la funci贸n 鈥渕ayorEstadosUnidos鈥:

if (persona1.esMayor(::mayorEstadosUnidos))
        println("${persona1.nombre} es mayor si vive en Estados Unidos")
    else
        println("${persona1.nombre} no es mayor si vive en Estados Unidos")

Como podemos comprobar el concepto de funciones de orden superior es aplicable a los m茅todos de una clase.

No hicimos un c贸digo m谩s conciso con el objeto que quede m谩s claro la sintaxis de funciones de orden superior, pero el mismo problema puede ser:

class Persona(val nombre: String, val edad: Int) {
    fun esMayor(fn:(Int) -> Boolean) = fn(edad)
}


fun mayorEstadosUnidos(edad: Int) = if (edad >= 21) true else false

fun mayorArgentina(edad: Int) = if (edad >= 18) true else false

fun main(parametro: Array<String>) {
    val persona1 = Persona("juan", 18)
    if (persona1.esMayor(::mayorArgentina))
        println("${persona1.nombre} es mayor si vive en Argentina")
    else
        println("${persona1.nombre} no es mayor si vive en Argentina")
    if (persona1.esMayor(::mayorEstadosUnidos))
        println("${persona1.nombre} es mayor si vive en Estados Unidos")
    else
        println("${persona1.nombre} no es mayor si vive en Estados Unidos")
}

Fuente: https://www.tutorialesprogramacionya.com/kotlinya/detalleconcepto.php?punto=36&codigo=36&inicio=30



B谩sicamente entend铆 que las funciones lambda son funciones que se pueden enviar como par谩metro a otras funciones. Esto por que los par谩metros de una funci贸n pueden variar en funci贸n de un dato.

fun main() {
//High-Order Function
    val resultHighOrder = addTwoNum(myLambdaFunc(2,2),myLambdaFunc(2,2))
    print(resultHighOrder) // result = 8
}
//{x, y-> x + y} Lambda: A function without name
fun addTwoNum(x: Int, y: Int):Int{ //Parameters
    return x + y //Method Body
}
//Lambda Expression
val myLambdaFunc: (Int, Int)-> Int = {x, y-> x + y}

La variable lambda se convierte en una Lambda heredando el tipo de input y return de funtionInception()

fun main() {
    val lambda : () -> String = funtionInception("Chair")
    println(lambda())
    // Consola = Objet from Lambda: Chair
}

fun funtionInception(name : String) : () -> String {
    return {"Objet from Lambda: $name"}
}
fun main() {
    val lambda = funtionInception(7)
    println(lambda(2))  //Consola = 3.5
}

fun funtionInception(number : Int) : (Int) -> Double {
    return {divider -> number.toDouble()/divider.toDouble()}
}

Block es una sintaxis recomendada por kotlin para nombrar las lambdas, puedes nombrar block cuando vas a ejecutar un codigo o la puedes llamar event o listener cuando vas a realizar una acci贸n dependiendo de un evento

ese tipo solo le importa que algunos entienda

pues esto es un callback 驴no?

Las funciones de orden superior son funciones que reciben como parametro a otras funciones, esto es un 鈥渢emplate鈥 o la forma mas generica de definir una funcion de orden superior.

Mas info aqui

C贸digo de la clase


fun main(args: Array<String>){
    var largoValorInit = superFunction(valorInit = "Hola", block = {
        it.length
    })
    println(largoValorInit)

    val lambda = functionInception("David")
    println(lambda())
}

fun superFunction (valorInit: String, block : (String)->Int) :Int {
    return block(valorInit)
}

fun functionInception (nombre:String): () -> String {
    return{
        "Hola"+" "+nombre
    }
}

Un ejemplo de una funci贸n de orden superior, que toma una funci贸n como par谩metro

/*--------------TOMANDO FUNCIONES COMO PAR脕METROS-----------------*/

//Declarando un funci贸n de orden superior. Toma dos par谩metros, x e y.
//Adicionalmente toma otra funci贸n como par谩metro.
//Los par谩metros de operaci贸n y el tipo de retorno tambi茅n se definen en la declaraci贸n
fun calculate(x: Int, y: Int, operation: (Int, Int) -> Int): Int {
    //La funci贸n de orden superior devuelve el resultado de la invocaci贸n de la operaci贸n con los argumentos proporcionados
    return operation(x, y)
}

//Declara una funci贸n que coincide con la firma de la operaci贸n
fun sum(x: Int, y: Int) = x + y

fun main() {
    //Invoca la funci贸n de orden superior pasando dos valores enteros y el argumento de la funci贸n ::suma
    //:: es la notaci贸n que hace referencia a una funci贸n por su nombre en Kotlin.
    val sumResult = calculate(4, 5, ::sum)

    //Invoca la funci贸n de orden superior pasando un lambda como argumento de funci贸n.
    val mulResult = calculate(4, 5) { a, b -> a * b }
    println("sumResult $sumResult, mulResult $mulResult")
fun main(args: Array<String>){
    var largoValorInit = superFunction(valorInit = "Hola", block = {
        it.length
    })
    println(largoValorInit)

    val lambda = functionInception("David")
    println(lambda())
}

fun superFunction (valorInit: String, block : (String)->Int) :Int {
    return block(valorInit)
}

fun functionInception (nombre:String): () -> String {
    return{
        "Hola"+" "+nombre
    }
}