Mastering Kotlin standard functions: run, with, let, also and apply

Mobile App Development Publication
6 min readNov 14, 2017

Some of the Kotlin’s standard functions are so similar that we are not sure which to use. Here I will introduce a simple way to clearly distinguish their differences and how to pick which to use.

Scoping functions

The functions that I’ll focus on are run, with,, T.let, T.also, and T.apply. I call them scoping functions as I view their main function is to provide an inner scope for the caller function.

The simplest way to illustrate scoping is the run function

fun test() {
var mood = "I am sad"
run {
val mood = "I am happy"
println(mood) // I am happy
println(mood) // I am sad

With this, inside the test function, you could have a separate scope where mood is redefined to I am happy before printing, and it is fully enclosed within the run scope.

This scoping function itself seems not very useful. But there’s another nice bit it has more than just the scope; it returns something i.e. the last object within the scope.

Hence the below would be neat, whereby we can apply the show() to both views as below, without calling it twice.

run {
if (firstTimeView) introView else normalView

3 attributes of scoping functions

To make scoping functions more interesting, let me categorize their behavior with 3 attributes. I will use these attributes to distinguish them from each other.

1. Normal vs. extension function

If we look at with and, both functions are pretty similar. The below does the same thing.

with(webview.settings) {
javaScriptEnabled = true
databaseEnabled = true
// {
javaScriptEnabled = true
databaseEnabled = true

However, their difference is one is a normal function i.e. with, while the other is an extension function i.e.

So the question is, what is the advantage of each?