0

Kotlin scope functions let, apply, also, run look like asynchronous callbacks. But they seem to be executed sequentially. How is this done? What are the implementation details?

1 Answers1

2

Scope functions are just meant to make your code easier to read and write. They are not asynchronous callbacks.

The scope functions do not introduce any new technical capabilities, but they can make your code more concise and readable.

In fact, they are inline functions. For example, apply is declared like this:

// Note "inline" modifier
public inline fun <T> T.apply(block: T.() -> Unit): T {
    block()
    return this
}

inline functions are inlined to their call site. For example, this code from the documentation:

val adam = Person("Adam").apply { 
    age = 20
    city = "London"
}
println(adam)

gets turned into something like this during compilation - the apply call is completely eliminated

val temp = Person("Adam")
temp.age = 20
temp.city = "London"
val adam = temp
println(adam)
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • Aren't all lambda functions like `fun(call: () -> Unit) { call() }`; asynchronous? Sorry if this sounds like a silly question :) I don't understand asynchronous programming that well. – truth seeker Mar 05 '22 at 15:39
  • @truthseeker I think we might not be on the same page here. What exactly do you mean by "asynchronous"? I had assumed that you meant it in the concurrency sense, in which case you would use coroutines and `suspend` functions to achieve it in Kotlin ([example](https://stackoverflow.com/questions/52369508/kotlin-coroutines-async-await-sequence)). – Sweeper Mar 05 '22 at 15:52
  • Wait, what do you mean @Sweeper ? Scoping functions are fully synchronous. Meaning that they don't do anything in the background, caller waits until the code in the lambda finishes executing. So answering OP's question: no, not all higher-order functions are asynchronous. Some are, some are not. – broot Mar 05 '22 at 16:24
  • @broot Yes, I understand that. I was thinking that OP *might* have some other definition of "asynchronous" in mind ("all functions that call some lambda" perhaps?), as they seem to think that `fun foo(call: () -> Unit) { call() }` is asynchronous. To be frank, I'm quite confused as to what exactly is the OP confused about. And this is why in my first comment, I was trying to get on the same page as them. – Sweeper Mar 05 '22 at 16:31
  • @broot Seeing how simple you have worded the answer, I think I probably have tried to read too much into OP's words... Silly me. – Sweeper Mar 05 '22 at 16:34
  • 2
    I think OP's confusion came from the assumption that the main/only reason to use callbacks is to provide a code that will be executed later. Because otherwise why do we use callbacks in the first place? We could just execute this code directly. But the fact is, there are many possible reasons or use cases when we would like to pass a callback for immediate and synchronous execution. Scoping functions is just one of examples. – broot Mar 05 '22 at 16:36
  • Sorry for the delayed response. First of all I need to thank you both of you to take the time to clear up my confusion. I understood the `inline` stuff; but I think I need to learn more about asynchronicity and should ask a better question. Thanks again. – truth seeker Mar 05 '22 at 17:52