Kotlin tutorial on generics and extension functions

Working my way through Kotlin tutorials, generics and extension functions

I've been working slowly through the Kotlin tutorials available at try.kotlin.org. The latest example I was working on really had me shaking my head about the syntax.

The goal is to write a function that can be called on any collection that will partition it into two via a predicate.

import java.util.*

fun <T, C: MutableCollection<T>> Collection<T>.partitionTo(first: C, second: C, predicate: (T) -> Boolean): Pair<C, C> {
    for (element in this) {
        if (predicate(element)) {
            first.add(element)
        } else {
            second.add(element)
        }
    }
    return Pair(first, second)
}

// Example usage 1
fun partitionWordsAndLines() {
    val (words, lines) = listOf("a", "a b", "c", "d e").
            partitionTo(ArrayList<String>(), ArrayList()) { s -> !s.contains(" ") }
    words == listOf("a", "c")
    lines == listOf("a b", "d e")
}

// Example usage 2
fun partitionLettersAndOtherSymbols() {
    val (letters, other) = setOf('a', '%', 'r', '}').
            partitionTo(HashSet<Char>(), HashSet()) { c -> c in 'a'..'z' | c in 'A'..'Z'}
    letters == setOf('a', 'r')
    other == setOf('%', '}')
}

Wow, look at that function definition for partitionTo!

fun <T, C: MutableCollection<T>> Collection<T>.partitionTo(first: C, second: C, predicate: (T) -> Boolean): Pair<C, C>

It's defining a function (fun) that returns a Pair of Collections (Pair<C, C>) where C is a type of MutableCollection of Ts and T is anything you want. It takes two such MutableCollection<T> as parameters (the destinations into which the elements should be partitioned) and a predicate, which is a function. The predicate returns true or false for any T passed to it, which determines whether the element should be added to the first or second collection. In both Example 1 and 2, the predicate is a lambda that follows the partitionTo call and its other parameters. That really throws me off. I am not used to languages that would have anything the function utilizes outside the list of parameters. I find it strange. But strangeness aside, the really neat thing about this to me is that we have written a function that can be called on any collection that is a Collection<T>. The <T, C: MutableCollection<T>> Collection<T>. mess is what's called the receiver type and we're writing an extension function that extends that type with new funtionality. The hassle of writing our partitionTo is all in service of making the example usages very straightforward (except for the lambda following the parameter list).