Don’t abuse Kotlin’s scope functions

Scope functions
Kotlin’s standard library contains several functions whose sole purpose is to execute a block of code within the context of an object.
When you call such a function on an object with a lambda expression provided, it forms a temporary scope.
M𝐚𝐤𝐞 𝐬𝐮𝐫𝐞 𝐰𝐡𝐞𝐧 𝐲𝐨𝐮 𝐮𝐬𝐞 𝐊𝐨𝐭𝐥𝐢𝐧’𝐬 𝐬𝐜𝐨𝐩𝐞 𝐟𝐮𝐧𝐜𝐭𝐢𝐨𝐧𝐬 𝐲𝐨𝐮 𝐮𝐧𝐝𝐞𝐫𝐬𝐭𝐚𝐧𝐝
- What each of those functions does
- How receiver accessible within the function’s scope [it, this]
- What they return

Accessing nullable properties
- Let say we have a property called
binding
in our fragment which isnullable
private var binding: FragmentBlankBinding? = null
How we can access this property in our code in a null-safe
manner
with
: If you have a lot of properties you will end up using?
everywhere inwith’s
block
with(binding) {
this?.root?.isVisible = true
}
How we can improve this :
let
: Although now you are null-safe and you don’t need to repeat?
but you need to useit
to access any property of the receiver 😬
binding?.let {
it.root.isVisible = true
}
2. run
: I prefer using this over all the other options because it’s null-safe
and concise
Here you can access the properties of the receiver without repeating this
everywhere
binding?.run {
root.isVisible = true
}
Creating objects
- Many developers writing code in
Kotlin
but they followJava’s
coding style
val intent = Intent()
intent.putExtra("Key", "value")
intent.putExtra("Key1", "value")
How we can improve 👆 this code to make sure it’s concise and Kotlin friendly:
let
: returns the result of thelambda
val intent = Intent().let {
it.putExtra("Key", "value")
it.putExtra("Key1", "value")
it.action = "CUSTOM_APP_ACTION" // Unit
}// here intent's type will be Unit 🥵// you can fix this by moving/removing last statementval intent = Intent().let {
it.putExtra("Key", "value")
it.action = "CUSTOM_APP_ACTION"
it.putExtra("Key1", "value") // Intent ✅
}
apply
: returns itsreceiver
val intent = Intent().apply {
putExtra("Key", "value")
putExtra("Key1", "value")
action = "CUSTOM_APP_ACTION"
}// here intent's type will be Intent ✅
When to use
with
, let
, apply
, also
, run
- If the property is
nullable
, you can uselet
orrun
val supportedJVM: String? = nullsupportedJVM?.run {receiver is avialble using this keyword // Lambda result will be the return value
}
supportedJVM?.let { receiver is avialble using it keyword // Lambda result will be the return value
}
- If the property is
non-nullable
, you can usewith
with(languageName) { receiver is avialble using this keyword
// Lambda result will be the return value
}
- You can use
also
when you want to do something additional work with an object orresult
of some other function or expression e.g.
var formattedPrice = ""val price = 10.plus(5).also { receiver is avialble using it keyword
formattedPrice = "Price is ${it * 2}"
// Context object will be the return value}