how Kotlin interpret {} or () by a run example

Viewed 55
fun main (){
    run(::topLevel)
    run{::topLevel}
    run{topLevel()}
    run(topLevel())
    }
fun topLevel() = println("print something")

1,2 run will execute the fun 3- will not execute 4- is an error

By this example i find that () and {} have different meaning. Would appreciate a lot if some one will explain how Kotlin interpret this 4 cases.

2 Answers

If you see the declaration of the run function,

public inline fun <R> run(block: () -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

It takes a block (a lambda) of signature () -> R. And the curly parenthesis ({}) create a lambda of that signature.

For instance {} has signature () -> Unit, { 4 } has signature () -> Int. These are compatible with the run function.

What essentially happens when you call run is:

run { topLevel() }

// is equivalent to
run() { topLevel() }

// is equivalent to
run({ topLevel })

Hope-fully you understood the lambdas, which are created by curly braces {} and can be put outside the invokation of the function.

Now if you talk about :: operator, it returns a reference of the function which is itself a lambda signature.

For example, ::topLevel will return () -> Unit as it takes no argument and returns nothing (which is Unit).


Second and fourth will not work because.

In second: run{::topLevel} this passes passes () -> () -> Unit to the run. i.e. it passes a function which returns a reference to function topLevel. And hence to make it work, you have to write:

run{::topLevel}()

What it does is return the ::topLevel on which we invoke using () that calls topLevel.

The fourth one won't compile because you are passing Unit (return type) of the topLevel function returned by calling it there like topLevel()

in kotlin when you use {} and write something in it it means you are passing a block to the trailing lambda.

when you use () means you are passing a value, so:

  1. run(someFunction()) -> this means you are passing the return value of someFunction() as a parameter to run() which will fail simply because run does not take a value as parameter, however it takes a lambda as a parameter.

  2. run{someFunction} -> this means you are passing a lambda or a block to be called inside run body. This will work cuz it simply satisfies run function signature.

public inline fun <R> run(block: () -> R): R
Related