Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Writing Higher-Order Functions

When you write a function, you must declare the types of its parameters. But how do you do that when one of those parameters is itself a function?

The general syntax for specifying a function type is

( parameter-types ) -> return-type

For example, consider this predicate:

fun isEnglishVowel(c: Char) = c.lowercase() in "aeiou"

The type of this function is

(Char) -> Boolean

Now let’s write a higher-order function that has a parameter of this type.

Imagine that we need a function howMany() to count the number of characters in a string that satisfy a given predicate. (There is actually no need for such a function, as strings support the count() operation already, but let’s pretend that this doesn’t exist…)

We could implement howMany() like so:

fun String.howMany(include: (Char) -> Boolean): Int {
    var count = 0
    for (character in this) {
        if (include(character)) {
            count += 1
        }
    }
    return count
}

Notice the String. prefix to the function name on the first line. This defines howMany() as an extension function of the String class and allows us to invoke it as if it were a method of that class.

howMany() has a single parameter, include, with a type of (Char) -> Boolean: i.e., a function that takes a single Char and returns a Boolean.

The for loop iterates over the characters of the string on which howMany() has been invoked. We refer to that string using the special variable name this.

Task 8.5

Try using the howMany() function described above.

  1. In the tasks/task8_5 subdirectory of your repository, create a file named Count.kt, containing the definition of howMany() shown above. Check that the code compiles before proceeding further.

  2. Add a main() function that creates a string and then calls howMany() on it in various ways, using different lambdas as the argument.