Kotlin Function Literals with Receiver – Quick Introduction

Kotlin Function Literals with Receiver - The Foundation for DSLs and many Library Functions

Today I want to give a quick introduction to Kotlin Function Literals with Receiver. This concept is what makes Kotlin great for designing Domain Specific Languages as we know it from Groovy for example. Also, Kotlin's standard library includes many functions which many of you have already used or at least seen probably: apply and with are the most prominent ones.

Preconditions

Kotlin, other than Java, has proper function types, which means that variables can, for example, be of type "function accepting an Int and returning a String": (Int)->String. These function types can be used as parameters to other functions, which are in turn called "higher order functions":

fun myHigherOrderFun(functionArg: (Int)->String) = functionArg(5)

As you can see myHigherOrderFunhas a parameter of a function type, which it can call in its method body. If we now want to use this higher order function, we can make use of lambdas, also referred to as "function literal":

println ( myHigherOrderFun { "The Number is $it" })
>> prints "The Number is 5"

Kotlin Function Literals with Receiver

As we've seen, function literals can be used as arguments to other functions, which is an awesome feature on its own. Nevertheless, Kotlin goes even further and supports the concept of "function literals with receivers". This enables us to call methods on the receiver of the function literal in its body without any specific qualifiers. This is very similar to extension functions, where it's also possible to access members of the receiver object inside the extension. Let's see, what function literals look like:

var greet: String.() -> Unit = { println("Hello $this") }

This one defines a variable of type String.() -> Unit, which is basically a function type () -> Unit with String as the receiver. All methods of this receiver can, therefore, be called in the method body. In this example, this is simply used to print the String. The function can be called like so:

greet("Hadi") 
>> prints "Hello Hadi"

This is essentially all you need to know, let's see a use case in action.

In Action - Scope Functions

As I already mentioned in the beginning, Kotlin's standard library contains methods using this concept, one of which is apply. This one is defined as follows:

public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }

As we can easily see, it's an extension function to everything literally, and it expects a function literal with a generic receiver of type T, which is run before the receiver is returned to the caller. This little function is actually fantastic as it provides a way to build certain objects very concisely and easily.

println(StringBuilder("Hello ")
        .apply {
            append("Kotliner")
            append("! ")
            append("How are you doing?")
        }.toString())
>> prints "Hello Kotliner! How are you doing?"

In this example, a StringBuilder is created and then the apply method is called on it. As we've seen before, it's possible to call any method of our receiver StringBuilder like append in the above code. Since apply returns the receiver after it completes, a call of toString on the StringBuilder can immediately be performed and the text is printed to the console.

Hope this helps! I really like this feature because it gives us so many possibilities. Probably it's one of Kotlin's most important ones 🙂 If you want to learn about creating DSLs, have a look here. I myself found so many spots in my code, which I could simplify a lot using these receiver-aware functions; Have a look at yours today 😉

Finally, if you want to read about Kotlin's beautiful features I recommend the book Kotlin in Action to you!

Simon

11 thoughts on “Kotlin Function Literals with Receiver – Quick Introduction

Leave a Reply

Your email address will not be published. Required fields are marked *