Higher-Order Functions in Kotlin

Kotlin includes a lot of powerful features from functional languages like Haskell. One of the main features that we think of as being characteristic of a functional language is the ability to use higher-order functions. Try this out in the exercises below.

Syntax reminder:

Here's a reminder of two different ways of passing a function as an argument to another function, either by function reference (double-colon), or by passing a lambda - an anonymous function declared in braces.

fun square(x: Int): Int = x * x fun main() { val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8) // passing a function reference val squares1 = numbers.map(::square) // passing a lambda val squares2 = numbers.map { x -> x * x } println(numbers) println(squares1) println(squares2) }

Try the following:

Write a function lengths() that takes a list of strings and returns a list of their lengths:

import org.junit.Assert import org.junit.Test class TestStringLengths() { @Test fun emptyList() { Assert.assertEquals(emptyList<Int>(), lengths(emptyList<String>())) } @Test fun singletonList() { Assert.assertEquals(listOf(6), lengths(listOf("kotlin"))) } @Test fun listOfNumbers() { Assert.assertEquals(listOf(6, 7), lengths(listOf("kotlin", "haskell"))) } } //sampleStart fun lengths() = TODO() //sampleEnd

Write a function complements() that takes a list of integers, and returns a list of pairs, where each pair contains the input number as the first element, and the total of the numbers in the pair makes 10.

import org.junit.Test import org.junit.Assert class TestComplements() { @Test fun emptyList() { Assert.assertEquals(emptyList<Pair<Int, Int>>(), complements(emptyList<Int>())) } @Test fun singletonList() { Assert.assertEquals(listOf(Pair(5,5)), complements(listOf(5))) Assert.assertEquals(listOf(Pair(1,9)), complements(listOf(1))) } @Test fun listOfNumbers() { Assert.assertEquals(listOf(Pair(1,9), Pair(2,8), Pair(9,1)), complements(listOf(1, 2, 9))) } } //sampleStart fun complements(nums: List<Int>) = TODO() //sampleEnd

Write a function matchingTotal(x, pairs) that takes a total, and list of pairs of integers, returning a list containing only those pairs where the sum of the elements of the pair matches the given total. If the x = 10, then (4,6) would be included, but (6,6) would be excluded.

import org.junit.Test import org.junit.Assert class TestMatchingTotal() { @Test fun emptyList() { Assert.assertEquals(emptyList<Pair<Int, Int>>(), matchingTotal(10, emptyList<Pair<Int, Int>>())) } @Test fun singletonList() { Assert.assertEquals(listOf(Pair(5,5)), matchingTotal(10, listOf(Pair(5,5)))) Assert.assertEquals(listOf(Pair(1,4)), matchingTotal(5, listOf(Pair(1,4)))) } @Test fun listOfNumbers() { Assert.assertEquals(listOf(Pair(1,4), Pair(2,3)), matchingTotal(5, listOf(Pair(1,4), Pair(4,4), Pair(2,3)))) } } //sampleStart val pairs = listOf(Pair(1, 9), Pair(3, 4), Pair(5, 5)) fun matchingTotal() = TODO() //sampleEnd