Chapters

Hide chapters

Functional Programming in Kotlin by Tutorials

First Edition · Android 12 · Kotlin 1.6 · IntelliJ IDEA 2022

Section I: Functional Programming Fundamentals

Section 1: 8 chapters
Show chapters Hide chapters

Appendix

Section 4: 13 chapters
Show chapters Hide chapters

D. Appendix D: Chapter 4 Exercise & Challenge Solutions
Written by Massimo Carli

Exercise 4.1

Can you write a lambda expression that calculates the distance between two points given their coordinates, x1, y1 and x2, y2? The formula for the distance between two points is distance = √(x2−x1)²+(y2−y1)².

Exercise 4.1 solution

You can approach this problem in different ways. Assuming you pass all the coordinates as distinct parameters, you can write the following code:

val distanceLambda = { x1: Double, y1: Double, x2: Double, y2: Double -> // 1
  val sqr1 = (x2 - x1) * (x2 - x1) // 2
  val sqr2 = (y2 - y1) * (y2 - y1) // 2
  Math.sqrt(sqr1 + sqr2) // 3
}

In this example, you:

  1. Define a lambda expression with four Double parameters for each set of coordinates.
  2. Calculate the square of the distances between coordinates x and y.
  3. Produce the final return result with the last expression of the lambda.

You can get the same result in other ways. Here’s one using the Point typealias:

typealias Point = Pair<Double, Double>

val distanceLambdaWithPairs = { p1: Point, p2: Point ->
  val sqr1 = Math.pow(p1.first - p2.first, 2.0)
  val sqr2 = Math.pow(p1.second - p2.second, 2.0)
  Math.sqrt(sqr1 + sqr2)
}

You can then test your lambdas with the following code:

fun main() {
  println(distanceLambda(0.0, 0.0, 1.0, 1.0))
  println(distanceLambdaWithPairs(0.0 to 0.0, 1.0 to 1.0))
}

When you run, you get:

1.4142135623730951
1.4142135623730951

Exercise 4.2

What’s the type for the lambda expression you wrote in Exercise 4.1?

Exercise 4.2 solution

The type of distanceLambda is:

val distanceLambda: (Double, Double, Double, Double) -> Double

The type of distanceLambdaWithPairs is:

val distanceLambdaWithPairs: (Point, Point) -> Double

Or:

val distanceLambdaWithPairs: (Pair<Double, Double>, Pair<Double, Double>) -> Double

Exercise 4.3

What are the types of the following lambda expressions?

val emptyLambda = {} // 1
val helloWorldLambda = { "Hello World!" } // 2
val helloLambda = { name: String -> "Hello $name!" } // 3
val nothingLambda = { TODO("Do exercise 4.3!") } // 4

Can you write an example of a lambda expression of the following type?

 typealias AbsurdType = (Nothing) -> Nothing

In this case, can you show how to invoke it?

Exercise 4.3 solution

You start by looking at:

val emptyLambda = {}

This is a lambda expression with no input parameters and no return value. Well, that’s not quite true in Kotlin. The expression is actually returning something: Unit. Its type is then:

val emptyLambda: () -> Unit

The type for:

val helloWorldLambda = { "Hello World!" }

Is:

val helloWorldLambda: () -> String

A little bit different is the type of:

val helloLambda = { name: String -> "Hello $name!" }

Which is:

val helloLambda: (String) -> String

Finally, you have something else a little different, like:

val nothingLambda = { TODO("Do exercise 4.3!") }

In this case, the return type is Nothing. The return type would also be Nothing if you throw an exception. The type nothingLambda is then:

val nothingLambda: () -> Nothing

Nothing and lambda

Given the type:

typealias AbsurdType = (Nothing) -> Nothing

You can write a function like the following:

val absurd: AbsurdType = { nothing -> throw Exception("This is Absurd") }

As you learned in Chapter 2, “Function Fundamentals”, the problem with the absurd lambda expression is that you need a value of type Nothing for its invocation. You might write:

fun main() {
  absurd(TODO("Invoked?"))
}

Because Kotlin uses strict evaluation, it evaluates the expression you pass as a parameter of absurd before the absurd itself. In this case, TODO doesn’t complete, so the absurd will never be invoked. The same happens with:

fun main() {
  absurd(throw Exception("Invoked?"))
}

Now, isn’t that absurd!

Exercise 4.4

Can you implement a function simulating the short-circuit and operator with the following signature without using &&? In other words, can you replicate the short-circuiting behavior of left && right:

  fun shortCircuitAnd(left: () -> Boolean, right: () -> Boolean): Boolean

Can you also write a test to prove that right evaluates only if left is false?

Exercise 4.4 solution

In Kotlin, if is an expression, so you can implement shortCircuitAnd like this:

fun shortCircuitAnd(
  left: () -> Boolean,
  right: () -> Boolean
): Boolean = if (left()) {
  right()
} else {
  false
}

In this lambda, right will only evaluate if left is true.

To test its behavior, you can use the following main:

fun main() {
  val inputValue = 2
  shortCircuitAnd(
    left = { println("LeftEvaluated!"); inputValue > 3 },
    right = { println("RightEvaluated!"); inputValue < 10 },
  )
}

Running this with inputValue = 2, you get:

LeftEvaluated!

Change inputValue = 10, and you get:

LeftEvaluated!
RightEvaluated!

This proves that shortCircuitAnd evaluates right only if left is true.

Exercise 4.5

Can you implement the function myLazy with the following signature, which allows you to pass in a lambda expression and execute it just once?

fun <A: Any> myLazy(fn: () -> A): () -> A // ???

Exercise 4.5 solution

myLazy accepts a lambda expression of type () -> A as an input parameter. It’s also important to note that A has a constraint, which makes it non-null. This makes the exercise a little bit easier, because you can write something like:

fun <A : Any> myLazy(fn: () -> A): () -> A {
  var result: A? = null // 1
  return { // 2
    if (result == null) { // 3
      result = fn() // 4
    }
    result!! // 5
  }
}

In this function, you:

  1. Use result as a local variable that tells you whether the lambda expression fn has been evaluated, and the value of type A can’t be null because of the constraint.
  2. Return a lambda of the same type, () -> A, as the input parameter.
  3. Check if result is null. This means fn hasn’t been evaluated yet.
  4. Evaluate fn and store the value in result, which now isn’t null anymore.
  5. Return result, which is always of type A.

To test myLazy, write:

fun main() {
  val myLazy = myLazy { println("I'm very lazy!"); 10 }
  3.times {
    println(myLazy())
  }
}

Run it, and you get:

I'm very lazy!
10
10
10

This proves the lambda expression is actually evaluated only once, and the result is simply reused.

You can remove the not nullability constraint in Challenge 4.1. See you there! :]

Exercise 4.6

Create a function fibo returning the values of a Fibonacci sequence. Remember, every value in a Fibonacci sequence is the sum of the previous two elements. The first two elements are 0 and 1. The first values are, then:

0  1  1  2  3  5  8  13  21 ...

Exercise 4.6 solution

The following is a possible implementation for the Fibonacci sequence using lambda evaluation:

fun fibo(): () -> Int {
  var first = 0
  var second = 1
  var count = 0
  return {
    val next = when (count) {
      0 -> 0
      1 -> 1
      else -> {
        val ret = first + second
        first = second
        second = ret
        ret
      }
    }
    count++
    next
  }
}

To test the previous code, you can use:

fun main() {
  val fiboSeq = fibo()
  10.times {
    print("${fiboSeq()}  ")
  }
}

Run it, and you get:

0  1  1  2  3  5  8  13  21  34  

Challenge 4.1

In Exercise 4.5, you created myLazy, which allowed you to implement memoization for a generic lambda expression of type ()-> A. Can you now create myNullableLazy supporting optional types with the following signature?

fun <A> myNullableLazy(fn: () -> A?): () -> A? // ...

Challenge 4.1 solution

To remove the constraint, you just need to use an additional variable, like this:

fun <A> myNullableLazy(fn: () -> A?): () -> A? {
  var evaluated = false // HERE
  var result: A? = null
  return { ->
    if (!evaluated) {
      evaluated = true
      result = fn()
    }
    result
  }
}

To test myNullableLazy, you can write:

fun main() {
  val myNullableLazy: () -> Int? =
    myNullableLazy { println("I'm nullable lazy!"); null }
  3.times {
    println(myNullableLazy())
  }
}

Run it, and you get:

I'm nullable lazy!
null
null
null

Challenge 4.2

You might be aware of Euler’s number e. It’s a mathematical constant of huge importance that you can calculate in very different ways. It’s an irrational number like pi that can’t be represented in the form n/m. Here you’re not required to know what it is, but you can use the following formula:

Figure 4.2: Euler's formula
Figure 4.2: Euler's formula

Can you create a sequence that provides the sum of the n terms of the given formula?

Challenge 4.2 solution

A possible implementation of the Euler formula is:

fun e(): () -> Double {
  var currentSum = 1.0 // 1
  var n = 1

  tailrec fun factorial(n: Int, tmp: Int): Int = // 2
    if (n == 1) tmp else factorial(n - 1, n * tmp)

  return {
    currentSum += 1.0 / factorial(n++, 1).toDouble() // 3
    currentSum
  }
}

This basically translates the formula in Figure 4.2 into code. Here, you:

  1. Initialize currentSum to the first value, which is 1.
  2. Implement factorial, which provides the factorial of a given number n. A factorial is the product of the number from 1 to n. For example 3 factorial would be 1 * 2 * 3.
  3. Return a lambda expression of type () -> Double, updating and returning currentSum.

Write and run the following code:

fun main() {
  val e = e()
  10.times {
    println(e())
  }
}

You get the following output:

2.0
2.5
2.6666666666666665
2.708333333333333
2.7166666666666663
2.7180555555555554
2.7182539682539684
2.71827876984127
2.7182815255731922
2.7182818011463845

The last value is 2.7182818011463845, which is a good approximation of Euler’s number.

Looking at the previous code, you can see an additional optimization. In fact, you calculate the factorial every time.

Why not also make it a sequence? In this case, you can write:

fun factSeq(): () -> Int {
  var partial = 1
  var n = 1
  return {
    partial *= n++
    partial
  }
}

This allows you to implement e in a better way, like this:

fun fastE(): () -> Double {
  var currentSum = 1.0
  val fact = factSeq()
  return {
    currentSum += 1.0 / fact().toDouble()
    currentSum
  }
}

You can then write and run the following code when you use fastE instead of e:

fun main() {
  val e = fastE() // HERE
  10.times {
    println(e())
  }
}

The output is exactly the same, just more performant:

2.0
2.5
2.6666666666666665
2.708333333333333
2.7166666666666663
2.7180555555555554
2.7182539682539684
2.71827876984127
2.7182815255731922
2.7182818011463845
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2026 Kodeco Inc.