Chain everything into a single statement

Kotlin provides a number of functional constructs that allow the concise chaining of operations into a single statement or expression.

One such construct is the apply function

When I first started using apply , I tended to throw as many related statements as I could into the apply block aiming to remove as many redundant references to the receiver object as possible.

Here’s an example of using apply that at one point seemed great, but, in my opinion, now feels like a misuse of the function.

Intent(this, MainActivity::class.java).apply {

putExtra("extra1", "foo")

putExtra("extra2", "goo")

startActivity(this)

}

It avoids storing a reference to the Intent , but mixing the configuration logic with the usage of the Intent makes the overall purpose of the code a bit harder to quickly discern.

That led to me looking deeper into the other, similar functions let , with , run , and also . I tried re-writing it like this:

Intent(this, MainActivity::class.java).apply {

putExtra("extra1", "foo")

putExtra("extra2", "goo")

}.run {

startActivity(this)

}

By removing startActivity(this) out of the apply block, it more clearly separates the configuration of the Intent and its usage. Unfortunately, moving the statement into run adds a bit of verbosity that Kotlin is generally good at avoiding.

For this type of situation, I’ve now moved away from trying to overuse these Kotlin functions, and simply storing the Intent in a val and referencing it in a separate statement. It’s 1 extra line of code, but much easier to quickly understand (in my opinion).

val newIntent = Intent(this, MainActivity::class.java).apply {

putExtra("extra1", "foo")

}

startActivity(newIntent)

If you still prefer everything be chained together you could try this as well

startActivity(Intent(this, MainActivity::class.java).apply {

putExtra("extra1", "foo")

})

I may have gone through several iterations of solving a similar problem, and abused some functions along the way, but I now have a much better understanding of the differences between let , apply , run , and with as well as an understanding of how those functions are actually implemented.

Ultimately this is a small example of a larger problem:

It’s very easy, tempting even, to make Kotlin code as concise as possible but in doing so, it may become less understandable. Finding a balance between brevity and readability is an ongoing and important part of diving into Kotlin.