Kotlin - Scope Functions (let, with, run, apply & also)
Armando Picón
Posted on February 22, 2021
Empecemos viendo este código:
name?.let{
//...
}
Estoy seguro que en algún momento lo has visto y sabes que es una forma de validar que name
no sea nulo antes de emplear el valor dentro del bloque de código dentro de la función let
. Pero ¿realmente sabes las implicancias del uso de dicha función? Si la respuesta es no, pues esta publicación es para ti.
Definiendo las scope functions
Según la documentación oficial son funciones cuyo único propósito es "ejecutar un bloque de código dentro del contexto de un objeto". Creo que la explicación es algo sencilla, básicamente es una forma de organizar nuestro código y hacerlo mejor leíble.
¿Qué scope functions trae Kotlin?
Básicamente tenemos 5 scope functions: let
, with
, run
, apply
y also
; adicionalmente hay 2 funciones extras takeIf
y takeUnless
que nos permitirán adicionar algunas validaciones de estado en medio de una cadena de invocación (o en tras palabras cuando concatenas varias scope functions) y que suelen emplearse junto con las 5 anteriores.
Como la documentación lo señala hay dos elementos que distinguen a una scope function de otra:
- la forma en que se referencia al objeto de contexto
- el valor de retorno
Por la forma en que se referencia al objeto de contexto
La razón por la que tenemos un it
o un this
es para simplificar o acortar el nombre de la variable original y, básicamente, te dirá si el objeto va a recibir la lambda (para el caso del this
) o si el objeto va a pasarse como argumento de la lambda (para el caso de it
).
Entonces, ¿en qué casos el objeto de contexto va a recibir la lambda? run
, with
y apply
y ¿en qué casos el objeto de contexto se pasará como argumento? let
y also
.
Por el valor de retorno
Para esta situación tendremos el retorno del mismo objeto de contexto para el caso de apply
y also
o el valor de resultado de la lambda en el caso de let
, run
y with
.
¿Qué función elegir?
Teniendo estas dos distinciones en mente, la documentación oficial detalla cada una de las funciones y los posibles escenarios de uso. De esa misma documentación saqué este cuadro que ayuda mucho a resumir lo dicho anteriormente:
Función | Referencia de objeto | Valor de retorno | ¿Es una extension function? |
---|---|---|---|
let |
it |
Resultado de la lambda | Sí |
run |
this |
Resultado de la lambda | Sí |
run |
- | Resultado de la lambda | No, cuando se llama sin el objeto de contexto |
with |
this |
Resultado de la lambda | No, porque toma el objeto de contexto como argumento |
apply |
this |
Objeto de contexto | Sí |
also |
it |
Objeto de contexto | Sí |
También la documentación brinda una pequeña guía de referencia:
- Ejecución de una lambda en objetos non-null:
let
- Introducir una expresión como una variable en un ámbito local:
let
- Configuración de un objeto:
apply
- Configuración de un objeto y computación del resultado:
run
- Ejecutar sentencias donde una expresión es requerida:
run
a secas sin objeto de contexto ni como función extendida - Efectos adicionales:
also
- Agrupar llamadas a funciones en un objeto:
with
takeIf y takeUnless
Estas dos funciones que vienen en la biblioteca estandar de Kotlin, no son consideradas scope functions; sin embargo, se emplean junto con ellas y sirven para realizar algunas validaciones.
La documentación oficial tiene algunos buenos ejemplos de cómo emplearlas.
Conclusión
Me resultan super interesantes las scope functions y este artículo tiene por intención hacer un breve resumen de en qué consisten y cuando emplearlas. Es importante practicar su uso para acostumbrarse a sus diferencias y casos de uso, dado que por lo similares que son resultado fácil confundirlas y equivocar su uso.
Posted on February 22, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.