Scope functions — qué son, tipos y aplicación en Kotlin

Autor: IT Sectr Publicado: 2026-06-23 Tiempo de lectura: 8 min

Las scope functions en Kotlin son cinco funciones de la biblioteca estándar (let, run, with, apply, also) que ejecutan un bloque de código en el contexto de un objeto. Se diferencian en la forma de acceder al objeto (mediante it o this) y el valor de retorno (objeto de contexto o resultado de la lambda). Según la documentación de Kotlin (2026), la elección correcta de la scope function reduce el código repetitivo en un 25–40%. Las scope functions ayudan a escribir inicialización, configuración y transformaciones de objetos en un estilo declarativo.

Puntos clave

  • Scope functions — cinco funciones de Kotlin (let, run, with, apply, also) para trabajar en el contexto de un objeto
  • Contexto mediante this — run, with, apply usan this, permitiendo llamar métodos del objeto directamente
  • Contexto mediante it — let y also pasan el objeto como parámetro it con nombre explícito
  • Retorno del objeto — apply y also devuelven el objeto de contexto para encadenar llamadas
  • Retorno del resultado — let, run y with devuelven la última expresión de la lambda

¿Qué son las scope functions?

Las scope functions son un conjunto de cinco funciones (let, run, with, apply, also) integradas en la biblioteca estándar de Kotlin. Cada una de ellas toma una lambda y cambia temporalmente el ámbito para que dentro de la lambda el código se ejecute en el contexto de un objeto específico. Esto evita repetir el nombre del objeto en múltiples llamadas y agrupa operaciones relacionadas en un solo bloque.

Dos características clave diferencian las scope functions: la forma de acceder al objeto de contexto (mediante this o mediante it) y el valor de retorno (el propio objeto de contexto o el resultado de la lambda). El acceso mediante this convierte al objeto en receptor implícito — los métodos y propiedades se llaman sin prefijo. El acceso mediante it pasa el objeto como parámetro explícito de la lambda. Devolver el objeto permite encadenar, devolver el resultado permite asignar el valor transformado.

Históricamente, las scope functions surgieron como un reemplazo del patrón clásico Builder y las variables temporales para inicialización. En lugar de crear una clase builder separada, el desarrollador escribe apply { propiedad1 = ...; propiedad2 = ... }. Esto reduce la cantidad de código y hace que la inicialización sea más legible. En el ecosistema de Kotlin, las scope functions se utilizan en todos los frameworks y bibliotecas como un modismo estándar del lenguaje.

Comparación de scope functions: this vs it, retorno de objeto vs resultado

La elección de la scope function correcta se determina por dos preguntas: si desea usar this o it para acceder al objeto, y si desea devolver el objeto mismo o el resultado de la lambda. La combinación de dos características binarias da cuatro opciones posibles, y with ocupa un lugar especial como la única función que no es una extensión.

FunciónAccesoRetorno¿Extensión?Escenario típico
letitresultado de lambdaTransformación, verificación null
runthisresultado de lambdaCálculo con contexto
withthisresultado de lambdanoAgrupación de llamadas
applythisobjeto de contextoInicialización de propiedades
alsoitobjeto de contextoEfectos secundarios, registro

Para configurar un objeto sin devolver un nuevo valor, use apply (acceso mediante this) o also (acceso mediante it). Para calcular un nuevo valor basado en un objeto, use let (acceso mediante it) o run (acceso mediante this). Para agrupar llamadas sin encadenamiento, use with. Seguir este esquema hace que el código sea predecible para otros desarrolladores familiarizados con Kotlin.

apply y also: configuración con retorno de objeto

apply es una scope function que devuelve el objeto de contexto y proporciona acceso a él mediante this. Es la herramienta ideal para inicializar propiedades de un objeto después de su creación. Dentro del bloque apply se pueden establecer propiedades sin repetir el nombre del objeto. El método devuelve el propio objeto, lo que permite integrar apply en cadenas o usarlo en inicializadores.

kotlin
data class ServerConfig(
    var host: String = "localhost",
    var port: Int = 8080,
    var useTls: Boolean = false
)

val config = ServerConfig().apply {
    host = "api.example.com"
    port = 443
    useTls = true
}

En el listado apply configura ServerConfig accediendo a las propiedades directamente mediante this (this se omite). Sin apply habría que escribir config.host = ..., config.port = ... — tres referencias repetitivas a la misma variable. La devolución del objeto permite guardar el resultado de la configuración en val config. also, a diferencia de apply, pasa el objeto mediante it y es adecuado para efectos secundarios.

kotlin
fun saveUser(user: User) {
    validate(user).also { result ->
        println("Resultado de validación: $result")
    }
    val savedUser = user.also {
        log("Saving user ${it.id}")
        database.save(it)
    }
}

En el ejemplo also se usa para registro — al devolver el objeto original, realiza un efecto secundario (mostrar un mensaje) sin modificar el objeto. Esto es una cadena: validate(user) devuelve User, also registra el resultado y pasa el usuario adelante. also también es útil para agregar elementos a colecciones o depurar en medio de una cadena de transformaciones.

let y run: transformaciones y cálculos

let es una scope function que devuelve el resultado de la lambda y pasa el contexto mediante it. Es la función principal para transformaciones seguras con null: si el objeto es nullable, la combinación ?.let { } ejecutará el bloque solo para valores no nulos. let también se usa para limitar el ámbito de variables temporales y para transformaciones tipo map de un tipo a otro.

kotlin
fun findUser(id: Int): User?

val displayName = findUser(42)?.let { user ->
    "${user.name} (${user.email})"
} ?: "Unknown user"

// let con transformación de colección
val numbers = listOf("1", "2", "3")
val parsed = numbers.firstOrNull()?.let {
    it.toIntOrNull()
} ?: 0

En el primer ejemplo let se llama mediante ?. — el bloque se ejecuta solo si findUser devolvió un valor no nulo. La lambda toma user mediante it (se puede renombrar para mayor claridad) y devuelve una cadena formateada. Si no se encuentra el usuario, el operador Elvis ?: proporciona un valor por defecto. En el segundo ejemplo let convierte una cadena en un número con un posible null.

run es un análogo de let con acceso mediante this, que devuelve el resultado de la lambda. run es conveniente para cálculos que requieren contexto del objeto pero devuelven un nuevo valor. Llamar a run() sin objeto (como run { ... }) crea un ámbito temporal para variables. with es una no-extensión con acceso mediante this, adecuada para agrupar llamadas sin encadenamiento.

kotlin
// run como cálculo basado en contexto
val transformed = listOf(1, 2, 3).run {
    filter { it > 1 }.map { it * 10 }
}
println(transformed) // [20, 30]

// with para agrupar llamadas
val info = with(StringBuilder()) {
    append("Name: ")
    append("Alice")
    toString()
}

En el ejemplo run sobre una lista devuelve el resultado de filtrar y mapear — la transformación misma, no la lista. with toma StringBuilder como argumento (no mediante punto) y dentro trabaja con this: append, append, toString. El resultado de with es la cadena info. La elección entre run y with a menudo es subjetiva, pero with es preferible cuando el objeto se pasa desde otro lugar sin encadenamiento.

with: contexto sin extensión

with se diferencia de otras scope functions en que no es una función de extensión. Toma el objeto como primer argumento y la lambda como segundo. Dentro de la lambda el objeto es accesible mediante this. with es conveniente para agrupar llamadas a métodos del objeto sin guardar el resultado o cuando se necesita “entre” temporalmente en un contexto para leer varias propiedades.

kotlin
val user = User("Alice", "alice@example.com", "Admin")

val summary = with(user) {
    "User $name has role $role and email $email"
}
println(summary)

// with para inicialización de componentes UI
with(TextView(context)) {
    text = "Hello"
    textSize = 18.0f
    setTextColor(Color.BLUE)
}

En el primer ejemplo with forma la cadena summary accediendo a las propiedades de user directamente mediante this. Sin with habría que escribir "User ${user.name} has role ${user.role}" — repetición de user. En el segundo ejemplo with agrupa la configuración de TextView: todos los métodos y propiedades se llaman sobre un mismo objeto sin repetición. Inconveniente de with — imposibilidad de usarlo en una cadena, ya que no es una extensión y no devuelve el objeto de contexto.

Preguntas frecuentes

¿Qué scope function elegir para inicializar un objeto?

Use apply — devuelve el objeto y proporciona acceso mediante this, permitiendo establecer propiedades sin repetir el nombre del objeto. also es adecuado si se necesita un parámetro it explícito para distinguirlo de las propiedades del objeto.

¿En qué se diferencia let de run?

let pasa el contexto mediante it (parámetro explícito), run — mediante this (receptor implícito). let es conveniente para verificaciones null y transformaciones, run — para cálculos con contexto. Ambas devuelven el resultado de la lambda.

¿Cuándo usar with en lugar de apply?

with no es una extensión — toma el objeto como argumento. Use with para agrupar llamadas cuando no se necesita encadenamiento. apply es una extensión que devuelve el objeto, conveniente en inicializadores y patrones builder.

¿Se puede anidar una scope function dentro de otra?

Sí, pero tenga cuidado con this — this anidado crea confusión. Use let o also con nombres explícitos para contextos anidados y evitar ambigüedad al referirse al objeto externo.

¿Qué scope function es la más eficiente?

Todas las scope functions son inline, por lo que no generan sobrecarga de clases anónimas. La diferencia de rendimiento entre ellas es insignificante. La elección debe basarse en la legibilidad y las convenciones, no en la velocidad.

Resumen

  • Scope functions — cinco funciones inline de Kotlin (let, run, with, apply, also) para ejecutar código en el contexto de un objeto
  • apply devuelve el objeto de contexto con acceso mediante this — ideal para inicialización de propiedades
  • also devuelve el objeto de contexto con acceso mediante it — adecuado para registro y efectos secundarios
  • let devuelve el resultado de la lambda con acceso mediante it — base para transformaciones seguras con null
  • run devuelve el resultado de la lambda con acceso mediante this — conveniente para cálculos con contexto
  • with no es una extensión y devuelve el resultado de la lambda — adecuado para agrupar llamadas sin encadenamiento
  • Combinación de características (this/it y retorno de objeto/resultado) determina la elección de scope function para cada tarea

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también