Background photo by Sonja Punz on Unsplash

Kotlin Fever : Part 3 — Lambdas and Higher Order Functions

Filip Babic
Published in
6 min readFeb 13, 2018

--

Third time’s the charm! Continuing with our awesome Kotlin in Android introduction series, this time we’ll be facing horrible monsters called Lambdas. Lambdas are often hated or feared (or both) by Java devs because of their weird syntax and usage.

There is a good explanation of lambdas in Java 8 by O’Reilly media, but as Kotlin’s lambdas are a bit different in syntax I’ll try to explain them in a noob friendly way.

So brace yourselves for an awesome journey. :)

Source : O’Reilly Media.

The Philosophy Behind

Most of the programming we do daily is asynchronous, in the background, where we take the responsibility of handling the result when, or if, it arrives. So with each request we do, with every UI event we have to react to, a need rises for more Callbacks.

In Android world there are two ways of handling a Callback, either by supplying an anonymous class (the ugly way), or by implementing the interface and passing this. Neither are pretty if you ask me, but that’s just the way it is. //(things will never be the same tntntn) 2pac ❤

Now, the second way doesn’t seem too bad, but just think of your regular onClickListeners. Having more than one causes you to do ugly switch statements which check the clicked view’s ID, so you can properly respond to the click. That’s where Butterknife from our Lord and Saviour Jake comes in. But you don’t need an external library for a clean onClickListener, or virtually any Listener when you’re using Kotlin!

So finally we come to the philosophy behind lambdas. A lambda is just an anonymous function, and it is very poor, all it has is a list of arguments and a body. It’s a block of code that’s encapsulated in a variable, which when called, executes the said block of code. So instead of calling a listener like this listener.doStuff(), you’d simply call the lambda with doStuff(). You create a lambda by opening curly braces and writing code inside it, and that’s it!

The syntax

view.setOnClickListener(object : OnClickListener {

override fun setOnClickListener(v: View?) {
//do stuff here
}

})

Standard anonymous way of handling click events. But even the compiler will say you should go with the lambda way! Using a quick Alt+enter action you get this:

//The longest form of passing a lambda
view.setOnClickListener ({ view ->
//do stuff
})
//If the method receives only the lambda, the () can be omitted
view.setOnClickListener { view ->
//do stuff
}
//If a lambda receives only a single argument, it can be omitted
view.setOnClickListener {
//do stuff
}

Now this is the stuff right here. We don’t have any anonymous implementations of an interface, and all the ugly code that comes with that. We’ve also omitted the parentheses because we’re not sending anything other than the lambda.

The view parameter can be ignored, which is not necessarily needed, but if you have only one argument in the lambda, you can remove it and use the implicit argument named it.

If you thought this couldn’t get simpler, think again!

fun View.onClick(onClick: () -> Unit) {
setOnClickListener { onClick() }
}
view.onClick { doStuffHere }

By creating an extension function, we can just declare onClicks by calling onClick on a View! How cool is that?

Okay, we get that creating a lambda is pretty easy, but how do we declare a method argument as a lambda?

The syntax for lambdas, or rather method references is (arguments) -> returnType. You state which type the arguments should be, and what’s the return type for the function. After that is done, any function that matches the description can be passed as a lambda.

fun someRequest(callback: (Data) -> Unit) {
//do stuff
}

What about methods which take a few arguments rather than one?

fun someRequest(callback: (Data, Int) -> Unit) {

}

The method declaration is more less the same, an argument is added in the method reference parentheses, nothing more. The call however changes a bit :

someRequest { data, id ->

val response = data.response

print("Received response : $response for the id $id")
}
//we underscored the "id" parameter as we're not using it
someRequest
{ data, _ ->
print("Received response : ${data.response}")
}

In case you have more than one argument, you cannot use the it, you have to name each argument differently, but if you’re not using an argument you can underscore it, to mark it unused.

Higher order functions

Regular functions receive only data parameters, whereas a function that receives another function as a parameter, or returns a function as a result is called a Higher order function. So, our functions that receive a lambda callback are basically higher order functions.

You might ask now, why would I want to return a lambda from another function? Well a common example would be animations in Android; you have a translation, but when going back you need to reverse it. In some Android APIs you can simply call .reverse(). Other times though, you cannot simply reverse it, so you turn to returning the animation itself, or its listener, and react to the onAnimationEnd callback.

In Kotlin though, you can just return a lambda, with the reverse animation parameters, and call the lambda later on when needed. We’ll check that out in a bit.

More Android please

We did see how an onClickListener could be replaced in a concise way, but it’s not the only benefit you get from using lambdas. I’ve personally really grown fond of animations due to lambdas, as creating reverse animations is as simple as returning a lambda, like I’ve mentioned above.

val reverseTranslation: (String) -> Unit = {
animate().translationX((-relativeX))
.translationY((-relativeY))
.setInterpolator(AccelerateDecelerateInterpolator())
.setDuration(duration)
.withEndAction {
onPickAction(it)
}
}

Might seem a bit complex, but what this does is create something called a method reference or a lambda object to put it simply. When called, it translates a view back to its original X and Y positions on the screen, and when the translation is done we call onPickAction which just notifies the activity/presenter that a category from a category picker has been selected.

The other thing that you could do is to wrap things like TextWatchers, focusChange listeners and so on in simple lambda powered structures.

fun View.onFocusChange(onFocusChange: (Boolean) -> Unit) = setOnFocusChangeListener { _, hasFocus -> onFocusChange(hasFocus) }

fun EditText.onTextChange(onTextChange: (String) -> Unit) = addTextChangedListener(SimpleTextWatcher { onTextChange(it) })

fun CompoundButton.onCheckedChange(onCheckedChange: (Boolean) -> Unit) = setOnCheckedChangeListener { _, isChecked -> onCheckedChange(isChecked) }

Rather than dirtying up your code with these various event handlers from Android, you can build simple extensions and hide it.

To sum it up

Lambdas have a thousand uses. Whenever you think: “Could I make this cleaner somehow?” there is a great chance that you can do it with a lambda. Moreover you can build DSLs with Lambdas and extensions, about which we could write a whole new article!

Filip Babić is an Android developer at COBE and a Computer Science student at FERIT, Osijek. He is a huge Kotlin fan, and occasionally holds mini work-shops and Kotlin meet-ups in Osijek. He likes to learn new stuff, play DnD and write about the things he loves the most. When he’s not coding, writing about coding, learning to code, or teaching others how to code, he nurtures his inner nerdiness by gaming and watching fantasy shows.

If you have any comments, or proposals to add to this article, or the series, be sure to let us know! :]

--

--

Writer for

Android developer. Praise Kotlin :] Keen and enthusiastic learner and mentor, passionate about teaching and helping others. GDE @ Android, Osijek, Croatia.