Kotlin es el nuevo lenguaje de programación para aplicaciones web y móviles interpolable con java. Kotlin puede producir código nativo para una variedad de plataformas:
- JVM
- Android
- Browser (web)
Una de las cosas que pueden resultar confusas al principio, por la variedad de usos que puede dársele, son las llamadas “scope functions” o en español funciones de alcance, las funciones de scope en Kotlin son las siguientes:
- also
- let
- apply
- run
- with
A continuación intentaré explicar cómo se usa cada uno:
Also
Esta función básicamente se leería “además haga esto con este objeto” resulta útil cuando queremos hacer debugging de los valores de los campos de un objeto.
Objeto .let { EntidadObjeto(it.nombre, it.valor) } .also { println(it.nombre) } .also { Objetos += it } .let { it.id }
Esta funcion tambien pasa un objeto en el parámetro y regresa el mismo objeto en lugar del resultado del lambda, como el patron de diseño builder
data class Persona(var nombre: String, var edad: Int) val persona = Persona("Edmundo", 42) val result = persona.also { person -> person.edad = 50 } println(persona) println(result)
La salida del anterior codigo seria la siguiente:
Persona(name=Edmundo, age=50) Persona(name=Edmundo, age=50)
En otras palabras, also toma el objeto original y devuelve el mismo objeto pero mutado de acuerdo a nuestras preferencias.
Let
let es una versión no monádica de map acepta objetos comp parameteros y regresa el resultado del lambda.
Ejemplo:
val persona = Persona("Edmundo", 42) val result = persona.let { it.edad * 2 } println(persona) println(result)
Resulta en:
Person(name=Edmund, age=42) 84
Apply
Es usado para configuración de objetos post-construccion. Es una función literal con un receptor donde el objeto no es pasado como un parámetro si no como el mismo (this) Es por eso que se le denomina “receptor”
Ejemplo con funciones:
val parser = ParserFactory.getInstance().apply{ setIndent(true) setLocale(Locale("hr", "HR")) }
Ejemplo con campos
val person = Persona("Edmundo", 42) val result = persona.apply { edad = 50 } println(persona) println(result)
resulta en:
Person(name=Edmundo, age=50) Person(name=Edmundo, age=50)
El anterior ejemplo también podría escribirse con notación de punto, así:
val person = Person("Edmund").apply { age = 50 }
Cuestión de gusto 🙂
Run
Es otra función literal con un receptor, la diferencia es que esta resuelve lambdas que no retornan un valor pero que producen un efecto colateral.
val persona = Persona("Edmundo", 42) val result = persona.run { edad * 2 } println(persona) println(result)
Resulta en:
Person(name=Edmund, age=42) 84
With
With debería usarse cuando se quieren llamar múltiples métodos de un objeto.
with(table) { clear() load("file.txt") }
with, regresa el resultado de evaluar la última expresión lo cual puede resultar confuso por lo que recomendaría que ignoremos el resultado que regresa “with”, si nos interesa uno de los valores lo ideal sería no usarlo. Cabe mencionar que tampoco funciona con valores anulables (nullable)
val persona = Persona("Edmundo", 42) val result = with(persona) { age * 2 } println(persona) println(result)
Resulta en:
Person(name=Edmund, age=42) 84
Las operaciones matemáticas en este contexto son consideradas un método.
Conclusiones
- also: procesamiento adicional en una llamada en cadena al objeto
- apply: configuracion post-construccion
- let: conversion de valores
- run: ejecución de lambdas con efectos colaterales y sin valor resultado
- with: configurar objetos creados en otro contexto
Algunos consejos:
- No use with con valores nullable
- No anidar apply, run y with ya que será difícil determinar el this actual
- Para also y let utilizar variables nombradas en lugar de it, por la misma razón que en el anterior consejo.
Claro que podríamos utilizar únicamente let para todo siempre, pero entonces se perdería la intención en el código, y esto es una parte importante de la programación funcional.
Todo esto toma algún tiempo en cuajar y podria ocasionar algun dolor de cabeza, pero conforme nos acostumbramos se va haciendo cada vez más fácil.
[…] sea que haya programado su aplicación en Kotlin o Java, el código DEX resultante es el mismo. Sin embargo, existen algunas ventajas significativas […]