Skip to content

A Note on Lambda Expressions

Daniel Chen edited this page Oct 2, 2024 · 8 revisions

What You Need to Know

This section assumes you have a basic understanding of kotlin lambdas. To read more, click here.

Lambda Functions with Context Receivers

An important detail you need to learn before learning the buildCommand DSL are lambdas with context receivers. In kotlin, a function object can accept parameters(like a regular function):

val functionObject: (Param1Type, Param2Type) -> ReturnType = { param1, param2 -> ReturnType() }

However, you can actually pass in up to one "context" receiver, like so:

val functionObject: ContextParameter.(Param1) -> ReturnType = { param1 -> ReturnType() } 

This acts like just a regular function parameter, except that it is not "declared" when the lambda is defined: instead, it is referred to with the this keyword instead. In other words, this makes the function object essentially a method(extension method) of the ContextParameter itself.

That concept sounds a little complicated, but in practice, it simply allows you to call methods of a Context parameter implicitly(as if you were calling it from within a class body), like so:

class ContextParam{ fun doSomething(){...} }
val functionObject: ContextParam.() -> Unit = { doSomething() }

To call a function object with a context parameter, it must be called within the class body of the context parameter, or as a method/extension method call, like so:

val contextFunctionObj: ContextParam.() -> Unit = ...
class ContextParam {
    init {
        contextFunctionObj()
    }
}
val output = ContextParam().contextFunctionObj()

Refer to the official kotlin docs here for more information.

External Lambda syntax

Another short titbit about kotlin lambda expressions is that they can be moved outside of the function block itself if they are the last(or only) argument of a higher-order function. For instance:

fun higherOrderFn(a: Double = 0.0, b: () -> Unit){ }
var output = higherOrderFn(2.0, {
    println("this way is decent...")
})
output = higherOrderFn(2.0) {
    println("But this way is better.")
}
output = higherOrderFn {
    println("You don't even have to put parentheses! (if all the other function arguments are optional)")
}