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