Functional collections

Functional collections are collections that offer a way to interact with its elements through high-order functions. Functional collections have common operations with names such as filter, map, and fold; these names are defined by convention (similar to a design pattern) and are being implemented in several libraries and languages.

Don't get confused with purely functional data structures—a data structure implemented in a pure functional language. A purely functional data structure is immutable and uses the lazy evaluation and other functional techniques.

Functional collections can but needn't necessarily be purely functional data structures. We have already covered how imperative implementations of algorithms can be faster than functional ones. 

Kotlin comes with an excellent functional collection library. Let's have a look at it:

val numbers: List<Int> = listOf(1, 2, 3, 4)

Our value numbers as a List<Int> type. Now, let's print its members as follows:

fun main(args: Array<String>) {
for(i in numbers) {
println("i = $i")
}
}

So far, so good, but it doesn't look very functional.

Worry no more; Kotlin collections include many functions that receive lambdas to operate on their members. We can replace this loop with a lambda as follows:

fun main(args: Array<String>) {
numbers.forEach { i -> println("i = $i") }
}

Now, let's transform our collection in the following code:

val numbers: List<Int> = listOf(1, 2, 3, 4)

fun main(args: Array<String>) {
val numbersTwice: List<Int> = listOf()

for (i in numbers) {
numbersTwice.add(i * 2) //Compilation error: Unresolved reference: add
}
}

This code doesn't compile; numberTwice doesn't have an add(T) method. List<T> is an immutable list; it can be modified once it is initialized. To add elements to a list, it must have a different type—MutableList<T> in our case:

val numbers: List<Int> = listOf(1, 2, 3, 4)

fun main(args: Array<String>) {
val numbersTwice: MutableList<Int> = mutableListOf()

for (i in numbers) {
numbersTwice.add(i * 2) //Nice!
}
}

MutableList<T> extends List<T>; it adds the methods to modify the collection itself, such as add(T), remove(T), clear, and others.

All major Kotlin collection types (List<T>, Set<T>, and Map<K, V>) have mutable subtypes (MutableList<T>, MutableSet<T>, and MutableMap<K, V>).

But we can replace this transformation with a single line expression as shown in the following code:

val numbers: List<Int> = listOf(1, 2, 3, 4)

fun main(args: Array<String>) {
val numbersTwice: List<Int> = numbers.map { i -> i * 2 }
}

The map operation lets you transform (technically mapping a value to another). This code has many advantages and is a lot cleaner, and now the numbersTwice value is a List<Int> list, instead of a MutableList<T> list.

Let's have another couple of examples. We can sum all elements of numbers using a loop:

val numbers: List<Int> = listOf(1, 2, 3, 4)

fun main(args: Array<String>) {
var sum = 0

for (i in numbers) {
sum += i
}

println(sum)
}

It could be reduced to just one line, with an immutable sum value as follows:

val numbers: List<Int> = listOf(1, 2, 3, 4)

fun main(args: Array<String>) {
val sum = numbers.sum()

println(sum)
}

Nice, but not interesting, so let's raise the stakes:

val numbers: List<Int> = listOf(1, 2, 3, 4)

fun main(args: Array<String>) {
val sum = numbers.fold(0) { acc, i -> acc + i }

println(sum)
}

The fold method iterates over a collection, keeping an accumulator value. fold takes a T value as the initial value; in the first iteration, this initial value will be the accumulator and subsequent iterations will use the lambda's return as the next accumulator value:

val numbers: List<Int> = listOf(1, 2, 3, 4)

fun main(args: Array<String>) {
val sum = numbers.fold(0) { acc, i ->
println("acc, i = $acc, $i")
acc + i
}

println(sum)
}

The output will look something like the following screenshot:

Similar to fold, reduce iterates over a collection, with an accumulator but without an initial value:

val numbers: List<Int> = listOf(1, 2, 3, 4)

fun main(args: Array<String>) {
val sum = numbers.reduce { acc, i ->
println("acc, i = $acc, $i")
acc + i
}

println(sum)
}

The output will look something like the following screenshot:

fold and reduce have counterparts in foldRight and reduceRight that start iterating from the last item to the first.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.35.122