Múltiples variables en let: el problema que no habías notado
¿Alguna vez has escrito en Kotlin y de repente te has dado cuenta: "Necesito procesar dos variables nullable a la vez"? Recurres a tu querido let, pero... espera. let solo funciona con una variable. ¿Y qué haces si tienes dos, tres o más?
Esta pregunta es una de las más populares en Stack Overflow sobre Kotlin. Miles de desarrolladores tropiezan con esta tarea, aparentemente simple. Y hoy vamos a entender de una vez por todas cómo resolverla de forma elegante y correcta.
En este artículo no solo daremos ejemplos secos. Compararemos 3 enfoques, discutiremos sus ventajas, desventajas y best practices. Aprenderás qué método elegir según la situación y dejarás de escribir horribles let anidados.
¿Por qué el problema "Multiple variable let" es tan popular?
Kotlin es un lenguaje que adora la seguridad contra nulos (null safety). Las funciones de ámbito (scope functions) — let, run, with, apply, also — son nuestra arma secreta para trabajar de forma segura con tipos nullable. Pero tienen una limitación: cada función está diseñada para un único objeto receptor.
Imagina esta situación: obtienes de una API dos campos nullable — el nombre de usuario y su correo electrónico. Necesitas verificar que ambos no sean null, y solo entonces realizar una acción (por ejemplo, enviar un correo de bienvenida).
Los principiantes suelen escribir así:
val name: String? = getUserName()val email: String? = getUserEmail()
if (name != null && email != null) { sendWelcomeEmail(name, email)}Esto funciona, pero no es la forma Kotlin. Podemos hacer el código más conciso y seguro. Veamos cómo.
Enfoque 1: let anidados — simple, pero poco elegante
La forma más obvia es anidar un let dentro de otro. Es lo primero que viene a la mente:
val name: String? = getUserName()val email: String? = getUserEmail()
name?.let { safeName -> email?.let { safeEmail -> sendWelcomeEmail(safeName, safeEmail) }}Ventajas:
- Funciona "de serie", no requiere funciones adicionales
- El código se lee de forma secuencial
Desventajas:
- Al aumentar el número de variables (3, 4 o más), el código se convierte en una "pirámide del horror"
- Difícil de leer y mantener
- Cada nivel anidado añade una sangría innecesaria
Este enfoque solo es adecuado para dos variables. Para tres o más, busca una alternativa.
Enfoque 2: Uso de Pair, Triple y data class
Kotlin proporciona las clases integradas Pair y Triple. La idea es combinar las variables nullable en un solo objeto y luego verificarlo mediante let.
val name: String? = getUserName()val email: String? = getUserEmail()
val pair = name?.let { n -> email?.let { e -> n to e }}
pair?.let { (safeName, safeEmail) -> sendWelcomeEmail(safeName, safeEmail)}Para tres variables usamos Triple:
val name: String? = getUserName()val email: String? = getUserEmail()val age: Int? = getUserAge()
val triple = name?.let { n -> email?.let { e -> age?.let { a -> Triple(n, e, a) } }}
triple?.let { (safeName, safeEmail, safeAge) -> sendWelcomeEmail(safeName, safeEmail, safeAge)}Ventajas:
- Sin anidamiento profundo en la llamada final
- La desestructuración hace que el código sea limpio
Desventajas:
- El anidamiento interno (al crear Pair/Triple) sigue existiendo
Triplees el máximo para la biblioteca estándar. Para 4+ variables necesitas