Kotlin: run, let, apply, also, with — ¿cuándo usar cada uno? Análisis completo con ejemplos
¡Hola, amigo! Si estás aprendiendo Kotlin y quieres escribir código limpio y conciso, tarde o temprano te encontrarás con cinco funciones mágicas: run, let, apply, also y with. Son las scope functions (funciones de ámbito) — te permiten ejecutar código en el contexto de un objeto y simplifican enormemente la vida.
Pero hay un problema: muchos principiantes (y no solo ellos) se confunden sobre cuándo aplicar cada una. Esta pregunta es una de las más populares en Stack Overflow, y hoy vamos a aclararlo de una vez por todas. No solo enumeraremos las reglas — mostraremos ejemplos reales de la práctica que podrás usar de inmediato en tus proyectos.
¿Qué son las scope functions y para qué sirven?
Las scope functions son funciones que crean un ámbito temporal para un objeto. Dentro de este ámbito, puedes acceder al objeto mediante it o this. La principal diferencia entre ellas es cómo devuelven el resultado y cómo hacen referencia al contexto.
Aquí tienes una chuleta rápida que iremos completando con ejemplos:
let— contexto:it, devuelve: resultado de la lambda. Se usa para comprobaciones no nulas y cadenas de llamadas.run— contexto:this, devuelve: resultado de la lambda. Función universal, a menudo para inicialización y cálculos.apply— contexto:this, devuelve: el propio objeto. Ideal para configurar propiedades de un objeto.also— contexto:it, devuelve: el propio objeto. Bueno para acciones adicionales (logging, comprobaciones).with— no es una función de extensión, contexto:this, devuelve: resultado de la lambda. Útil para agrupar llamadas de un objeto sin crear uno nuevo.
Recuerda la regla principal: la elección de la función depende de lo que necesites — devolver el objeto o el resultado, y cómo quieras acceder al contexto (mediante it o this).
1. let — el rey de las cadenas seguras
let es tu mejor amigo cuando necesitas trabajar con objetos nullable. Ejecuta el código solo si el objeto no es null. El contexto se pasa como it.
Ejemplo: transformación segura
val name: String? = "Andrés"// Sin let:if (name != null) { println("Longitud del nombre: ${name.length}")}
// Con let (mucho más elegante):name?.let { println("Longitud del nombre: ${it.length}")}let también es excelente para cadenas de operaciones. Por ejemplo, cuando necesitas transformar un objeto en otro:
val numbers = listOf(1, 2, null, 4, null, 6)val nonNullSquared = numbers .mapNotNull { it } .let { list -> list.map { it * it } }println(nonNullSquared) // [1, 4, 16, 36]Cuándo usar let:
- Comprobación de null (el caso más común).
- Transformar un valor en otro.
- Ejecutar una cadena de operaciones con el resultado.
2. apply — constructor sin rodeos
apply devuelve el propio objeto, y dentro de la lambda el contexto es this. Es la herramienta ideal para configurar un objeto antes de usarlo. ¡Olvídate de los largos bloques de set!
Ejemplo: configuración de View (Android) o data class
data class User(var name: String = "", var age: Int = 0)
val user = User().apply { name = "María" age = 25}println(user) // User(name=María, age=25)
// Aún mejor — configuración de TextView:val textView = TextView(context).apply { text = "¡Hola, Kotlin!" textSize = 18f setTextCo