Capacitación de Kotlin para programadores 3: Funciones

Este codelab es parte del curso de capacitación de Kotlin para programadores. Aprovecharás al máximo este curso si trabajas con los codelabs de forma secuencial. Según tus conocimientos, es posible que puedas cambiar algunas secciones. Este curso está dirigido a programadores que conocen un lenguaje orientado a objetos y quieren aprender Kotlin.

Introducción

En este codelab, crearás un programa de Kotlin y aprenderás sobre las funciones en Kotlin, incluidos valores predeterminados para parámetros, filtros, lambdas y funciones compactas.

En lugar de crear una sola app de ejemplo, las lecciones de este curso están diseñadas para ampliar tus conocimientos, pero son semiindependientes entre sí para que puedas revisar las secciones con las que ya estás familiarizado. Para unirlos, muchos de los ejemplos usan un tema de acuario. Si quieres ver la historia completa del acuario, consulta el curso de Udacity Kotlin Bootcamp for Programmers.

Conocimientos que ya deberías tener

  • Los conceptos básicos de un lenguaje de programación moderno, orientado a objetos y con escritura estática
  • Cómo programar con clases, métodos y control de excepciones en al menos un lenguaje
  • Cómo trabajar con el REPL (bucle de lectura, evaluación e impresión) de Kotlin en IntelliJ IDEA
  • Los conceptos básicos de Kotlin, incluidos los tipos, los operadores y los bucles

Este codelab está dirigido a programadores que conocen un lenguaje orientado a objetos y desean obtener más información sobre Kotlin.

Qué aprenderás

  • Cómo crear un programa con una función main() y argumentos en IntelliJ IDEA
  • Cómo usar valores predeterminados y funciones compactas
  • Cómo aplicar filtros a las listas
  • Cómo crear lambdas y funciones de orden superior básicas

Actividades

  • Trabaja con el REPL para probar algo de código.
  • Trabajar con IntelliJ IDEA para crear programas básicos en Kotlin

En esta tarea, crearás un programa en Kotlin y aprenderás sobre la función main(), así como a pasar argumentos a un programa desde la línea de comandos.

Tal vez recuerdes la función printHello() que ingresaste en el REPL en un codelab anterior:

fun printHello() {
    println ("Hello World")
}

printHello()
⇒ Hello World

Las funciones se definen con la palabra clave fun, seguida del nombre de la función. Al igual que con otros lenguajes de programación, los paréntesis () se usan para los argumentos de la función, si los hay. Las llaves {} enmarcan el código de la función. No hay un tipo de datos que se muestre para esta función, ya que no devuelve nada.

Paso 1: Crea un archivo Kotlin

  1. Abre IntelliJ IDEA.
  2. El panel Project que se encuentra a la izquierda en IntelliJ IDEA muestra una lista de los archivos y las carpetas de tu proyecto. Busca la carpeta src y haz clic con el botón derecho en ella. (Ya deberías tener el proyecto Hello Kotlin del codelab anterior).
  3. Selecciona New > Kotlin File / Class.
  4. Mantén Kind como File y asigna el nombre Hello al archivo.
  5. Haz clic en Aceptar.

Ahora hay un archivo en la carpeta src llamado Hello.kt.

Paso 2: Agrega código y ejecuta tu programa

  1. Al igual que con otros lenguajes, la función main() de Kotlin especifica el punto de entrada para la ejecución. Todos los argumentos de la línea de comandos se pasan como un array de cadenas.

    Escribe o pega el siguiente código en el archivo Hello.kt :
fun main(args: Array<String>) {
    println("Hello, world!")
}

Al igual que tu función printHello() anterior, esta función no tiene ninguna instrucción return. Todas las funciones en Kotlin devuelven algo, incluso cuando no se especifica nada de forma explícita. Por lo tanto, una función como esta main() devuelve un tipo kotlin.Unit, que es la forma en que Kotlin indica que no hay ningún valor.

  1. Para ejecutar el programa, haz clic en el triángulo verde que se encuentra a la izquierda de la función main(). Selecciona Run 'HelloKt' en el menú.
  2. IntelliJ IDEA compila el programa y lo ejecuta. Los resultados aparecen en un panel de registro en la parte inferior, como se muestra a continuación.

Paso 3: Pasa argumentos a main()

Como ejecutas tu programa desde IntelliJ IDEA y no desde la línea de comandos, debes especificar los argumentos del programa de una manera un poco diferente.

  1. Selecciona Run > Edit Configurations. Se abrirá la ventana Run/Debug Configurations.
  2. Escribe Kotlin! en el campo Argumentos del programa.
  3. Haz clic en Aceptar.

Paso 4: Cambia el código para usar una plantilla de cadena

Una plantilla de cadena inserta una variable o expresión en una cadena, y $ especifica que esa parte de la cadena será una variable o expresión. Las llaves {} enmarcan la expresión, si hay alguna.

  1. En Hello.kt, cambia el mensaje de saludo para usar el primer argumento que se pasa al programa, args[0], en lugar de "world".
fun main(args: Array<String>) {
    println("Hello, ${args[0]}")
}
  1. Ejecuta el programa. El resultado incluirá el argumento que especificaste.
⇒ Hello, Kotlin!

En esta tarea, aprenderás por qué casi todo en Kotlin tiene un valor y por qué eso es útil.

Otros lenguajes tienen instrucciones, que son líneas de código que no tienen un valor. En Kotlin, casi todo es una expresión y tiene un valor, incluso si ese valor es kotlin.Unit.

  1. En Hello.kt, escribe código en main() para asignar un println() a una variable llamada isUnit y, luego, imprímela. (println() no devuelve un valor, por lo que devuelve kotlin.Unit).
// Will assign kotlin.Unit
val isUnit = println("This is an expression")
println(isUnit)
  1. Ejecuta el programa. El primer println() imprime la cadena "This is an expression". El segundo println() imprime el valor de la primera instrucción println(), es decir, kotlin.Unit.
⇒ This is an expression
kotlin.Unit
  1. Declara un val llamado temperature y, luego, inicialízalo en 10.
  2. Declara otro val llamado isHot y asígnale el valor de devolución de una instrucción if/else a isHot, como se muestra en el siguiente código. Como es una expresión, puedes usar el valor de la expresión if de inmediato.
val temperature = 10
val isHot = if (temperature > 50) true else false
println(isHot)
⇒ false
  1. Usar el valor de una expresión en una plantilla de cadena Agrega código para verificar la temperatura y determinar si un pez es seguro o está demasiado caliente, y, luego, ejecuta el programa.
val temperature = 10
val message = "The water temperature is ${ if (temperature > 50) "too warm" else "OK" }."
println(message)
⇒ The water temperature is OK.

En esta tarea, aprenderás más sobre las funciones en Kotlin y sobre la expresión condicional when, que es muy útil.

Paso 1: Crea algunas funciones

En este paso, combinarás parte de lo que aprendiste y crearás funciones con diferentes tipos. Puedes reemplazar el contenido de Hello.kt con este código nuevo.

  1. Escribe una función llamada feedTheFish() que llame a randomDay() para obtener un día de la semana aleatorio. Usa una plantilla de cadena para imprimir un food para que el pez coma ese día. Por ahora, los peces comen el mismo alimento todos los días.
fun feedTheFish() {
    val day = randomDay()
    val food = "pellets"
    println ("Today is $day and the fish eat $food")
}

fun main(args: Array<String>) {
    feedTheFish()
}
  1. Escribe la función randomDay() para elegir un día aleatorio de un array y devolverlo.

La función nextInt() toma un límite entero, que limita el número de Random() a 0 a 6 para que coincida con el array week.

fun randomDay() : String {
    val week = arrayOf ("Monday", "Tuesday", "Wednesday", "Thursday",
            "Friday", "Saturday", "Sunday")
    return week[Random().nextInt(week.size)]
}
  1. Las funciones Random() y nextInt() se definen en java.util.*. En la parte superior del archivo, agrega la importación necesaria:
import java.util.*    // required import
  1. Ejecuta el programa y verifica el resultado.
⇒ Today is Tuesday and the fish eat pellets

Paso 2: Usa una expresión when

Para ampliar esto, cambia el código para elegir diferentes alimentos para diferentes días con una expresión when. La sentencia when es similar a switch en otros lenguajes de programación, pero when se interrumpe automáticamente al final de cada rama. También se asegura de que tu código abarque todas las ramas si estás verificando un enum.

  1. En Hello.kt, agrega una función llamada fishFood() que tome un día como String y muestre la comida del pez para el día como String. Usa when() para que cada día el pez reciba un alimento específico. Ejecuta el programa varias veces para ver diferentes resultados.
fun fishFood (day : String) : String {
    var food = ""
    when (day) {
        "Monday" -> food = "flakes"
        "Tuesday" -> food = "pellets"
        "Wednesday" -> food = "redworms"
        "Thursday" -> food = "granules"
        "Friday" -> food = "mosquitoes"
        "Saturday" -> food = "lettuce"
        "Sunday" -> food = "plankton"
    }
    return food
}

fun feedTheFish() {
    val day = randomDay()
    val food = fishFood(day)

    println ("Today is $day and the fish eat $food")
}
⇒ Today is Thursday and the fish eat granules
  1. Agrega una rama predeterminada a la expresión when con else. Para realizar pruebas y asegurarte de que, a veces, se toma el valor predeterminado en tu programa, quita las ramas Tuesday y Saturday.

    Tener una rama predeterminada garantiza que food obtenga un valor antes de devolverse, por lo que ya no es necesario inicializarlo. Como el código ahora asigna una cadena a food solo una vez, puedes declarar food con val en lugar de var.
fun fishFood (day : String) : String {
    val food : String
    when (day) {
        "Monday" -> food = "flakes"
        "Wednesday" -> food = "redworms"
        "Thursday" -> food = "granules"
        "Friday" -> food = "mosquitoes"
        "Sunday" -> food = "plankton"
        else -> food = "nothing"
    }
    return food
}
  1. Dado que cada expresión tiene un valor, puedes hacer que este código sea un poco más conciso. Muestra el valor de la expresión when directamente y elimina la variable food. El valor de la expresión when es el valor de la última expresión de la rama que satisfizo la condición.
fun fishFood (day : String) : String {
    return when (day) {
        "Monday" -> "flakes"
        "Wednesday" -> "redworms"
        "Thursday" -> "granules"
        "Friday" -> "mosquitoes"
        "Sunday" -> "plankton"
        else -> "nothing"
    }
}

La versión final de tu programa se parece al siguiente código:

import java.util.*    // required import

fun randomDay() : String {
    val week = arrayOf ("Monday", "Tuesday", "Wednesday", "Thursday",
        "Friday", "Saturday", "Sunday")
    return week[Random().nextInt(week.size)]
}

fun fishFood (day : String) : String {
    return when (day) {
        "Monday" -> "flakes"
        "Wednesday" -> "redworms"
        "Thursday" -> "granules"
        "Friday" -> "mosquitoes"
        "Sunday" -> "plankton"
        else -> "nothing"
    }
}

fun feedTheFish() {
    val day = randomDay()
    val food = fishFood(day)
    println ("Today is $day and the fish eat $food")
}

fun main(args: Array<String>) {
    feedTheFish()
}

En esta tarea, aprenderás sobre los valores predeterminados para funciones y métodos. También aprenderás sobre las funciones compactas, que pueden hacer que tu código sea más conciso y legible, y pueden reducir la cantidad de rutas de código para las pruebas. Las funciones compactas también se denominan funciones de expresión única.

Paso 1: Crea un valor predeterminado para un parámetro

En Kotlin, puedes pasar argumentos por nombre de parámetro. También puedes especificar valores predeterminados para los parámetros: si el llamador no proporciona un argumento, se usa el valor predeterminado. Más adelante, cuando escribas métodos (funciones miembro), podrás evitar escribir muchas versiones sobrecargadas del mismo método.

  1. En Hello.kt, escribe una función swim() con un parámetro String llamado speed que imprima la velocidad del pez. El parámetro speed tiene un valor predeterminado de "fast".
fun swim(speed: String = "fast") {
   println("swimming $speed")
}
  1. Desde la función main(), llama a la función swim() de tres maneras. Primero, llama a la función con el valor predeterminado. Luego, llama a la función y pasa el parámetro speed sin un nombre. Luego, llama a la función nombrando el parámetro speed.
swim()   // uses default speed
swim("slow")   // positional argument
swim(speed="turtle-like")   // named parameter
⇒ swimming fast
swimming slow
swimming turtle-like

Paso 2: Agrega los parámetros obligatorios

Si no se especifica un valor predeterminado para un parámetro, siempre se debe pasar el argumento correspondiente.

  1. En Hello.kt, escribe una función shouldChangeWater() que tome tres parámetros: day, temperature y un nivel de dirty. La función devuelve true si se debe cambiar el agua, lo que sucede si es domingo, si la temperatura es demasiado alta o si el agua está demasiado sucia. Se requiere el día de la semana, pero la temperatura predeterminada es de 22 y el nivel de suciedad predeterminado es de 20.

    Usa una expresión when sin un argumento, que en Kotlin actúa como una serie de verificaciones de if/else if.
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20): Boolean {
    return when {
        temperature > 30 -> true
        dirty > 30 -> true
        day == "Sunday" ->  true
        else -> false
    }
}
  1. Llama a shouldChangeWater() desde feedTheFish() y proporciona el día. El parámetro day no tiene un valor predeterminado, por lo que debes especificar un argumento. Los otros dos parámetros de shouldChangeWater() tienen valores predeterminados, por lo que no es necesario que pases argumentos para ellos.
fun feedTheFish() {
    val day = randomDay()
    val food = fishFood(day)
    println ("Today is $day and the fish eat $food")
    println("Change water: ${shouldChangeWater(day)}")
}
=> Today is Thursday and the fish eat granules
Change water: false

Paso 3: Crea funciones compactas

La expresión when que escribiste en el paso anterior incluye mucha lógica en una pequeña cantidad de código. Si quisieras desglosarlo un poco más o si las condiciones que se deben verificar fueran más complicadas, podrías usar algunas variables locales con nombres descriptivos. Sin embargo, la forma de hacerlo en Kotlin es con funciones compactas.

Las funciones compactas, o funciones de una sola expresión, son un patrón común en Kotlin. Cuando una función devuelve los resultados de una sola expresión, puedes especificar el cuerpo de la función después de un símbolo =, omitir las llaves {} y omitir el return.

  1. En Hello.kt, agrega funciones compactas para probar las condiciones.
fun isTooHot(temperature: Int) = temperature > 30

fun isDirty(dirty: Int) = dirty > 30

fun isSunday(day: String) = day == "Sunday"
  1. Cambia shouldChangeWater() para que llame a las funciones nuevas.
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20): Boolean {
    return when {
        isTooHot(temperature) -> true
        isDirty(dirty) -> true
        isSunday(day) -> true
        else  -> false
    }
}
  1. Ejecuta el programa. El resultado de println() con shouldChangeWater() debería ser el mismo que antes de que comenzaras a usar funciones compactas.

Valores predeterminados

El valor predeterminado de un parámetro no tiene que ser un valor. Puede ser otra función, como se muestra en el siguiente ejemplo parcial:

fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = getDirtySensorReading()): Boolean {
    ...

En esta tarea, aprenderás un poco sobre los filtros en Kotlin. Los filtros son una forma práctica de obtener parte de una lista según alguna condición.

Paso 1: Crea un filtro

  1. En Hello.kt, define una lista de decoraciones para el acuario en el nivel superior con listOf(). Puedes reemplazar el contenido de Hello.kt.
val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")
  1. Crea una función main() nueva con una línea para imprimir solo las decoraciones que comienzan con la letra "p". El código de la condición del filtro se encuentra entre llaves {}, y it hace referencia a cada elemento a medida que se repite el filtro. Si la expresión devuelve true, el elemento se incluye.
fun main() {
    println( decorations.filter {it[0] == 'p'})
}
  1. Ejecuta el programa y verás el siguiente resultado en la ventana Run:
⇒ [pagoda, plastic plant]

Paso 2: Compara los filtros eager y lazy

Si conoces los filtros en otros lenguajes, es posible que te preguntes si los filtros en Kotlin son eager o lazy. ¿La lista de resultados se crea de inmediato o cuando se accede a ella? En Kotlin, sucede de la forma que lo necesites. De forma predeterminada, filter es eager y, cada vez que usas el filtro, se crea una lista.

Para que el filtro sea diferido, puedes usar un Sequence, que es una colección que solo puede mirar un elemento a la vez, comenzando por el principio y llegando hasta el final. Convenientemente, esta es exactamente la API que necesita un filtro diferido.

  1. En Hello.kt, cambia tu código para asignar la lista filtrada a una variable llamada eager y, luego, imprímela.
fun main() {
    val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")

    // eager, creates a new list
    val eager = decorations.filter { it [0] == 'p' }
    println("eager: " + eager)
  1. Debajo de ese código, evalúa el filtro con un Sequence y asSequence(). Asigna la secuencia a una variable llamada filtered y, luego, imprímela.
   // lazy, will wait until asked to evaluate
    val filtered = decorations.asSequence().filter { it[0] == 'p' }
    println("filtered: " + filtered)

Cuando devuelves los resultados del filtro como un Sequence, la variable filtered no contendrá una lista nueva, sino un Sequence de los elementos de la lista y el conocimiento del filtro que se aplicará a esos elementos. Cada vez que accedes a elementos de Sequence, se aplica el filtro y se te devuelve el resultado.

  1. Fuerza la evaluación de la secuencia convirtiéndola en un List con toList(). Imprime el resultado.
    // force evaluation of the lazy list
    val newList = filtered.toList()
    println("new list: " + newList)
  1. Ejecuta tu programa y observa el resultado.
⇒ eager: [pagoda, plastic plant]
filtered: kotlin.sequences.FilteringSequence@386cc1c4
new list: [pagoda, plastic plant]

Para visualizar lo que sucede con la evaluación Sequence y la evaluación diferida, usa la función map(). La función map() realiza una transformación simple en cada elemento de la secuencia.

  1. Con la misma lista de decorations que se mostró anteriormente, realiza una transformación con map() que no haga nada y que simplemente devuelva el elemento que se pasó. Agrega un println() para mostrar cada vez que se accede a un elemento y asigna la secuencia a una variable llamada lazyMap.
    val lazyMap = decorations.asSequence().map {
        println("access: $it")
        it
    }
  1. Imprime lazyMap, imprime el primer elemento de lazyMap con first() y, luego, imprime lazyMap convertido en un List.
    println("lazy: $lazyMap")
    println("-----")
    println("first: ${lazyMap.first()}")
    println("-----")
    println("all: ${lazyMap.toList()}")
  1. Ejecuta el programa y observa el resultado. Imprimir lazyMap solo imprime una referencia a Sequence; no se llama a println() interno. Imprimir el primer elemento solo accede a él. Convertir el Sequence en un List permite acceder a todos los elementos.
⇒ lazy: kotlin.sequences.TransformingSequence@5ba23b66
-----
access: rock
first: rock
-----
access: rock
access: pagoda
access: plastic plant
access: alligator
access: flowerpot
all: [rock, pagoda, plastic plant, alligator, flowerpot]
  1. Crea un nuevo Sequence con el filtro original antes de aplicar map. Imprime ese resultado.
    val lazyMap2 = decorations.asSequence().filter {it[0] == 'p'}.map {
        println("access: $it")
        it
    }
    println("-----")
    println("filtered: ${ lazyMap2.toList() }")
  1. Ejecuta el programa y observa el resultado adicional. Al igual que con la obtención del primer elemento, el println() interno solo se llama para los elementos a los que se accede.
⇒
-----
access: pagoda
access: plastic plant
filtered: [pagoda, plastic plant]

En esta tarea, obtendrás una introducción a las lambdas y las funciones de orden superior en Kotlin.

Lambdas

Además de las funciones con nombre tradicionales, Kotlin admite lambdas. Una lambda es una expresión que crea una función. En lugar de declarar una función con nombre, declaras una que no lo tiene. Parte de lo que hace que esto sea útil es que la expresión lambda ahora se puede pasar como datos. En otros lenguajes, las lambdas se conocen como funciones anónimas, literales de funciones o nombres similares.

Funciones de orden superior

Puedes crear una función de orden superior pasando una expresión lambda a otra función. En la tarea anterior, creaste una función de orden superior llamada filter. Pasaste la siguiente expresión lambda a filter como la condición para verificar:
{it[0] == 'p'}

Del mismo modo, map es una función de orden superior, y la expresión lambda que le pasaste fue la transformación que se aplicaría.

Paso 1: Obtén información sobre las lambdas

  1. Al igual que las funciones con nombre, las funciones lambda pueden tener parámetros. En el caso de las lambdas, los parámetros (y sus tipos, si es necesario) se colocan a la izquierda de lo que se denomina una flecha de función ->. El código que se ejecutará se encuentra a la derecha de la flecha de la función. Una vez que la expresión lambda se asigna a una variable, puedes llamarla como si fuera una función.

    Con el REPL (Tools > Kotlin > Kotlin REPL), prueba este código:
var dirtyLevel = 20
val waterFilter = { dirty : Int -> dirty / 2}
println(waterFilter(dirtyLevel))
⇒ 10

En este ejemplo, la expresión lambda toma un Int llamado dirty y devuelve dirty / 2. (porque el filtrado quita la suciedad).

  1. La sintaxis de Kotlin para los tipos de funciones está estrechamente relacionada con su sintaxis para las lambdas. Usa esta sintaxis para declarar de forma clara una variable que contiene una función:
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }

Esto es lo que dice el código:

  • Crea una variable llamada waterFilter.
  • waterFilter puede ser cualquier función que tome un Int y muestre un Int.
  • Asigna una expresión lambda a waterFilter.
  • La función lambda devuelve el valor del argumento dirty dividido por 2.

Ten en cuenta que ya no tienes que especificar el tipo del argumento lambda. El tipo se calcula por inferencia de tipo.

Paso 2: Crea una función de orden superior

Hasta ahora, los ejemplos de lambdas se parecen mucho a las funciones. El verdadero poder de las expresiones lambda radica en usarlas para crear funciones de orden superior, en las que el argumento de una función es otra función.

  1. Escribe una función de orden superior. Este es un ejemplo básico, una función que toma dos argumentos. El primer argumento es un número entero. El segundo argumento es una función que toma un número entero y devuelve un número entero. Pruébalo en el REPL.
fun updateDirty(dirty: Int, operation: (Int) -> Int): Int {
   return operation(dirty)
}

El cuerpo del código llama a la función que se pasó como segundo argumento y le pasa el primer argumento.

  1. Para llamar a esta función, pásale un número entero y una función.
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }
println(updateDirty(30, waterFilter))
⇒ 15

La función que pasas no tiene que ser una lambda; puede ser una función con nombre normal. Para especificar el argumento como una función normal, usa el operador ::. De esta manera, Kotlin sabe que estás pasando la referencia de la función como un argumento y no intentando llamar a la función.

  1. Intenta pasar una función con nombre normal a updateDirty().
fun increaseDirty( start: Int ) = start + 1

println(updateDirty(15, ::increaseDirty))
⇒ 16
var dirtyLevel = 19;
dirtyLevel = updateDirty(dirtyLevel) { dirtyLevel -> dirtyLevel + 23}
println(dirtyLevel)
⇒ 42
  • Para crear un archivo fuente de Kotlin en IntelliJ IDEA, comienza con un proyecto de Kotlin.
  • Para compilar y ejecutar un programa en IntelliJ IDEA, haz clic en el triángulo verde junto a la función main(). El resultado aparecerá en una ventana de registro a continuación.
  • En IntelliJ IDEA, especifica los argumentos de la línea de comandos para pasar a la función main() en Run > Edit Configurations.
  • Casi todo en Kotlin tiene un valor. Puedes usar este hecho para que tu código sea más conciso usando el valor de un if o when como una expresión o un valor de retorno.
  • Los argumentos predeterminados eliminan la necesidad de tener varias versiones de una función o un método. Por ejemplo:
    fun swim(speed: String = "fast") { ... }
  • Las funciones compactas, o de una sola expresión, pueden hacer que tu código sea más legible. Por ejemplo:
    fun isTooHot(temperature: Int) = temperature > 30
  • Aprendiste algunos conceptos básicos sobre los filtros, que usan expresiones lambda. Por ejemplo:
    val beginsWithP = decorations.filter { it [0] == 'p' }
  • Una expresión lambda es una expresión que crea una función sin nombre. Las expresiones lambda se definen entre llaves {}.
  • En una función de orden superior, pasas una función, como una expresión lambda, a otra función como datos. Por ejemplo:
    dirtyLevel = updateDirty(dirtyLevel) { dirtyLevel -> dirtyLevel + 23}

Esta lección contiene mucha información, sobre todo si no conoces las expresiones lambda. En una lección posterior, se volverá a abordar el tema de las lambdas y las funciones de orden superior.

Documentación de Kotlin

Si deseas obtener más información sobre algún tema de este curso o si te quedas atascado, https://kotlinlang.org es el mejor punto de partida.

Instructivos de Kotlin

El sitio web https://try.kotlinlang.org incluye instructivos enriquecidos llamados Kotlin Koans, un intérprete basado en la Web y un conjunto completo de documentación de referencia con ejemplos.

Curso de Udacity

Para ver el curso de Udacity sobre este tema, consulta Capacitación de Kotlin para programadores.

IntelliJ IDEA

Encontrarás la documentación de IntelliJ IDEA en el sitio web de JetBrains.

En esta sección, se enumeran las posibles actividades para el hogar para los alumnos que trabajan en este codelab como parte de un curso dirigido por un instructor. Depende del instructor hacer lo siguiente:

  • Si es necesario, asigna una tarea.
  • Comunicarles a los alumnos cómo enviar las actividades para el hogar.
  • Califica las actividades para el hogar.

Los instructores pueden usar estas sugerencias en la medida que quieran y deben asignar cualquier otra actividad para el hogar que consideren apropiada.

Si estás trabajando en este codelab por tu cuenta, usa estas actividades para el hogar para probar tus conocimientos.

Responde estas preguntas:

Pregunta 1

La función contains(element: String) devuelve true si la cadena element se encuentra en la cadena a la que se llama. ¿Cuál será el resultado del siguiente código?

val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")

println(decorations.filter {it.contains('p')})

[pagoda, plastic, plant]

[pagoda, plastic plant]

[pagoda, plastic plant, flowerpot]

[rock, alligator]

Pregunta 2

En la siguiente definición de función, ¿cuál de los parámetros es obligatorio?
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20, numDecorations: Int = 0): Boolean {...}

numDecorations

dirty

day

temperature

Pregunta 3

Puedes pasar una función con nombre normal (no el resultado de llamarla) a otra función. ¿Cómo pasarías increaseDirty( start: Int ) = start + 1 a updateDirty(dirty: Int, operation: (Int) -> Int)?

updateDirty(15, &increaseDirty())

updateDirty(15, increaseDirty())

updateDirty(15, ("increaseDirty()"))

updateDirty(15, ::increaseDirty)

Continúa con la siguiente lección: 4. Clases y objetos

Para obtener una descripción general del curso, incluidos los vínculos a otros codelabs, consulta "Capacitación de Kotlin para programadores: Bienvenido al curso".