APUNTES KOTLIN
  • Presentación
  • Apuntes Linux
  • Apuntes Blue Team
  • Apuntes Red Team
  • Apuntes Python
  • Ricardev github
  • CURSO BÁSICO
    • Tema 1. Kotlin Básico
    • Tema 2. Variables y Tipos de Datos
    • Tema 3. Números en Kotlin
    • Tema 4. Strings en Kotlin
    • Tema 5. Condicionales
    • Tema 6. Bucles
    • Tema 7. Saltos y Returns
    • Tema 8. Arrays en Kotlin
    • Tema 9. Colecciones. Listas
    • Tema 10. Colecciones. Set
    • Tema 11. Colecciones. Mapas
    • Tema 12.Manejo de Excepciones
  • Programación Funcional
    • Tema 12. Funciones
    • Funciones de Extensión
    • Funciones de Orden Superior
    • Funciones Lambda
    • Funciones de Alcance
  • PROGRAMACIÓN ORIENTADA A OBJETOS
    • Teoría POO
    • Clases y Objetos
    • Constructores
    • Getters y Setters
    • Herencia
    • Polimorfismo
    • Herencia múltiple
    • Otros Conceptos
Powered by GitBook
On this page
  • ANTECEDENTES
  • Funciones de orden superior
  • Funciones como variable
  • DEFINICIÓN
  • SINTÁXIS
  • Función lambda con cuerpo
  • IDENTIFICADOR IT
  • ACCESO A VARIABLES EXTERNAS
  • EJEMPLOS DE APLICACIÓN
  • Omitir el paréntesis
  • Ejemplo por partes
  1. Programación Funcional

Funciones Lambda

Explicación de las funciones lambda, su sintaxis, sus características y sus usos.

PreviousFunciones de Orden SuperiorNextFunciones de Alcance

Last updated 2 years ago

ANTECEDENTES

Como ya hemos visto en el tema anterior, son funciones que tienen como argumento una función o incluso devuelven una función.

Funciones como variable

Por otra parte, también podemos guardar funciones como variables en Kotlin aprovechándonos de los datos de tipo Función que implementa su gramática.

var suma = { x: Int, y: Int -> x + y  }

El bloque de código anterior es completamente válido y además nos permite cambiar el bloque de código que se ejecuta, por ejemplo, en cada iteración.

DEFINICIÓN

En base a lo visto anteriormente, podemos definir el concepto de función lambda como:

O, en otras palabras, una función anónima que utilizamos como valor de entrada en una función de orden superior.

SINTÁXIS

Continuando con la función suma, podemos escribirla así:

fun suma(x: Int, y: Int) = x + y

Para transformarla al formato lambda tenemos que hacerla anónima.

La sintaxis de un literal de lambda va escrita entre llaves {...} y su contenido es el siguiente:

  • Lista de parámetros — Cada parámetro es una declaración de variable, aunque esta lista es opcional

  • Operador de flecha -> — Se omite si no usas lista de parámetros

  • Cuerpo del lambda — Son las sentencias que van luego del operador de flecha

{ x: Int, y: Int -> x + y}

Función lambda con cuerpo

Las funciones lambda tienen que devolver un valor, eso es indispensable. Sin embargo, el cuerpo de una función lambda puede tener varias sentencias:

// Función lambda para hayar la potencia de x elevado a y.
{ x: Int, y: Int -> 
    var res = 1
    for (i in 1..y) res *= x
    res
}

IDENTIFICADOR IT

Cuando tu lambda usa un único argumento y no piensas cambiar su nombre por cuestiones de legibilidad, puedes usar el identificador it.

Esta variable se deduce implícitamente con el tipo inferido por el compilador y puedes referirte a ella como tu parámetro.

Vamos a mostrar un caso de uso con todo lo que hemos visto anteriormente:

var array1 = Array(5) { 5 }
var array2 = Array(5) { it }
var array3 = Array(5) { it * 2 }

println(array1.contentToString())    // [5, 5, 5, 5, 5]
println(array2.contentToString())    // [0, 1, 2, 3, 4]
println(array3.contentToString())    // [0, 2, 4, 6, 8]

En el caso del tipo Array, el argumento que coge la lambda es el iterador. Por tanto, it será el número de iteración.

ACCESO A VARIABLES EXTERNAS

Las lambdas pueden acceder a variables que se hayan inicializado fuera del código de la lambda:

fun recorrerArray(array: Array<Int>, fn: (Int) -> Unit) {
    for (i in array) {
        fn(i)
    }
}

fun main() {
    val array3 = Array(5) { it * 2 }
    var suma = 0
    recorrerArray(array3) {
        suma += it
    }
    println(suma)    // 20
}

EJEMPLOS DE APLICACIÓN

Las lambdas tienen un caso de uso claro con las funciones de orden superior como lo que vamos a ver a continuación:

// Declaración de función de orden superior
fun calculadora(x: Int, y: Int, fn: (Int, Int) -> Int): Int {
    return fn(x, y)
}
// uso con lambdas
println("La suma de $x y $y es: ${calculadora(x, y, { x: Int, y: Int -> x + y })}")
println("La resta de $x y $y es: ${calculadora(x, y, { x: Int, y: Int -> x - y })}")
println("La multiplicación de $x por $y es: ${calculadora(x, y, 
{ x: Int, y: Int -> x * y })}")
println("La división de $x entre $y es: ${calculadora(x, y, 
{ x: Int, y: Int -> x / y })}")

println("La potencia de $x elevado a $y es: ${calculadora(x, y,
{ x: Int, y: Int -> 
    var res = 1
    for (i in 1..y) res *= x
    res
})}")

/* Resultado
La suma de 5 y 5 es: 10
La resta de 5 y 5 es: 0
La multiplicación de 5 por 5 es: 25
La división de 5 entre 5 es: 1
La potencia de 5 elevado a 5 es: 3125 */

Omitir el paréntesis

Sin embargo, las lambdas por definición se pueden poner fuera de los paréntesis lo que hace el código más legible:

println("La suma de $x y $y es: ${calculadora(x, y) { x: Int, y: Int -> x + y }}")

Ejemplo por partes

Ejemplo básico

// Implementación de una variable que almecena la cantidad de 'i' en una String.
val s = "Supercalifragilisticoespialidoso"
val iCounter = s.count({ char:Char -> char == 'i' })

println("En la frase: $s")        // En la frase: Supercalifragilisticoespialidoso
println("Hay $iCounter ies.")     // Hay 6 ies.

Ejemplo omitiendo los paréntesis

// La lambda se puede sacar de los paréntesis
val s = "Supercalifragilisticoespialidoso"
val iCounter = s.count() { char:Char -> char == 'i' }

// Los paréntesis vacíos se pueden omitir
val s = "Supercalifragilisticoespialidoso"
val iCounter = s.count { char:Char -> char == 'i' }

Ejemplo omitiendo el tipo de dato

// El tipo de dato se puede omitir ya que count se aplica solo a tipo char.
val s = "Supercalifragilisticoespialidoso"
val iCounter = s.count { char -> char == 'i' }

Ejemplo del identificador it

En el ejemplo anterior lo que hemos hecho ha sido renombrar el argumento como char. Eso se puede omitir tambien.

// Se puede omitir el argumento de manera explícita.
// De esta manera el argumento se llamará it implícitamente:
val s = "Supercalifragilisticoespialidoso"
val iCounter = s.count { it == 'i' }

Una es un literal de función que puede ser usado como expresión. Esto quiere decir, una función que no está ligada a un identificador y que puedes usar como valor.

función lambda
Funciones de orden superior
Lambdas En Kotlin - DevelouDevelou
Fuente: develou
Logo