Android Kotlin Basics – Lambdas and Higher Order Functions

About This Series

This “Android Kotlin Basics” blog series is all about fundamentals. We’ll take a look at the basics of building Android apps with Kotlin from the SUPER basics, to the standard basics, to the not-so-basics. We’ll also be drawing comparisons to how things are done in Kotlin vs. Java and some other programming languages to build Android apps (like C# and Xamarin or JavaScript/TypeScript for Hybrid implementations).

Check Out the Pluralsight Course!

If you like this series, be sure to check out my course on Pluralsight – Building Android Apps with Kotlin: Getting Started where you can learn more while building your own real-world application in Kotlin along the way. You can also join the conversation and test your knowledge throughout the course with learning checks through each module!

Watch it here: https://app.pluralsight.com/library/courses/building-android-apps-kotlin-getting-started/table-of-contents

Lambdas and Higher Order Functions

Lambdas and Higher Order Functions are a great tool to use in development to pass logic around between different blocks in our code. This allows us to pass functions into other functions and execute them when we need to, and there are a few different ways to do this, but let’s start with Higher Order Functions in general.

Higher Order Functions

Higher order functions are ones that consume another function as a parameter. This means the higher order function can execute the inner function any number of times. This is commonly used for wrapping function calls, manipulating collections with the given function, or executing a callback function. Here’s an example of what that looks like with a callback function:

fun makeHttpGetRequest(string url, callback: (data: String) -> String) {
    url.httpGet() // using Fuel library as an example
       .responseString { request, response, result ->
      //do something with response
      when (result) {
          is Result.Failure -> {
              error = result.getAs()
              callback(error) // executing the passed in function
          }
          is Result.Success -> {
              data = result.getAs()
              callback(error) // executing the passed in function
          }
    }
}

In this example, we created a wrapper function for making an HTTP GET request that executes the callback function with either the error string or data as a string. Even more, we use another higher order function from the Fuel library responseString that takes in a Triple or a lambda/function with three parameters.

We define our inner function like so:

(<parameters>) -> <return type>

If your inner function does not have a return type, you simply set the return type as the Kotlin Unit – the equivalent of void. If you’re coming from F#, that will look familiar. That means a lambda with no parameters and no return type would be:

() -> Unit

Ways to Use Lambdas and Higher Order Functions

Basically, there are a few different ways you can define a function and pass that in as the parameter of the higher order function.
You could:

  • Define the function ahead of time and pass the definition in
  • Construct a Lambda Expression or Anonymous Function when invoking the higher order function

Let’s look at the first example of predefining a function to pass in. Let’s use the higher order function map that is an extension function on a List:

fun <T, R> List<T>.map(transform: (T) -> R): List<R> {
    val result = arrayListOf<R>()
    for (item in this)
        result.add(transform(item))
    return result
}

This method takes in a transform function to handle how to map the initial List of type T to a new List of type R, and the higher order function uses the transform function to execute against each item in the original list.
If you’re coming from C#, this is like the .Select() LINQ extension method.

Let’s now define our transform method we want to use and pass it in to a map call:

// define some simple classes
class Dog (val breed: String) { }
class Pet(val petType: String, val breed: String){ }

fun createPetFromDog(dog: Dog) : Pet {
    return Pet("dog", dog.breed)
}

var dogs = List<Dog>()
// fill with dogs

var pets = dogs.map(::createPetFromDog);

We use the :: prefix to inform the compiler that this is an existing function or other member.

Now let’s look at creating this same scenario, but using lambda expressions instead. There are even a few ways we can do this too!

// define some simple classes
class Dog (val breed: String) { }
class Pet(val petType: String, val breed: String){ }

var dogs = List<Dog>()
// fill with dogs

// define the transform function as an explicit lambda
var pets1 = dogs.map({dog -> Pet("dog", dog.breed));

// define the transform function, but outside the actual parameters
// this is a shortcut provided by Kotlin to help with readability
// note that the "()" after the map is not required when defining it this way
var pets2 = dogs.map(){ dog ->
    return Pet("dog", dog.breed) // note the return here is not technically required
}

// use the "it" keyword since we only have one parameter.
// the "it" keyword is another shortcut provided by Kotlin
// for lambdas with only 1 parameter
var pets3 = dogs.map { Pet("dog", it.breed) }

Notice how many different ways we can execute the exact same thing in the end. We see this in many places with Kotlin, and it gives us as developers the freedom to define a bit of our own style in the code of our projects, or to use different strategies at different times to help with readability.

Now get out there and start using nested functions!

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s