Kotlin Higher-Order Functions

Functions that work with other functions as parameters or return values

🚀 What are Higher-Order Functions?

Higher-order functions can take other functions as parameters or return functions as results. They enable powerful functional programming patterns, code reuse, and elegant solutions to complex problems.


// Higher-order function that takes a function as parameter
fun calculate(x: Int, y: Int, operation: (Int, Int) -> Int): Int {
    return operation(x, y)
}

fun main() {
    val sum = calculate(5, 3) { a, b -> a + b }
    val product = calculate(5, 3) { a, b -> a * b }
    
    println("Sum: $sum")       // Sum: 8
    println("Product: $product") // Product: 15
}
                                    

Output:

Sum: 8

Product: 15

Higher-Order Function Types

📥

Function Parameters

Accept functions as arguments

fun process(data: Int, action: (Int) -> Int) {
    return action(data)
}
📤

Function Returns

Return functions as results

fun getMultiplier(factor: Int): (Int) -> Int {
    return { x -> x * factor }
}
🔄

Function Composition

Combine multiple functions

fun compose(f: (Int) -> Int, g: (Int) -> Int): (Int) -> Int {
    return { x -> f(g(x)) }
}
âš¡

Built-in Functions

map, filter, reduce, etc.

// Built-in higher-order functions
list.map { it * 2 }.filter { it > 5 }

🔹 Functions as Parameters

Pass functions as arguments to create flexible, reusable code:

// Higher-order function with function parameter
fun applyOperation(numbers: List, operation: (Int) -> Int): List {
    return numbers.map(operation)
}

fun repeatAction(times: Int, action: () -> Unit) {
    repeat(times) {
        action()
    }
}

fun main() {
    val numbers = listOf(1, 2, 3, 4, 5)
    
    // Pass different operations
    val doubled = applyOperation(numbers) { it * 2 }
    val squared = applyOperation(numbers) { it * it }
    val negated = applyOperation(numbers) { -it }
    
    println("Original: $numbers")
    println("Doubled: $doubled")
    println("Squared: $squared")
    println("Negated: $negated")
    
    // Repeat an action
    repeatAction(3) { println("Hello!") }
}

Output:

Original: [1, 2, 3, 4, 5]

Doubled: [2, 4, 6, 8, 10]

Squared: [1, 4, 9, 16, 25]

Negated: [-1, -2, -3, -4, -5]

Hello!

Hello!

Hello!

🔹 Functions Returning Functions

Create functions that generate other functions:

// Function that returns a function
fun createValidator(minLength: Int): (String) -> Boolean {
    return { input -> input.length >= minLength }
}

fun createFormatter(prefix: String, suffix: String): (String) -> String {
    return { text -> "$prefix$text$suffix" }
}

fun createCounter(start: Int): () -> Int {
    var current = start
    return { ++current }
}

fun main() {
    // Create specialized validators
    val isValidPassword = createValidator(8)
    val isValidUsername = createValidator(3)
    
    println("Password 'abc123' valid: ${isValidPassword("abc123")}")     // false
    println("Password 'abc12345' valid: ${isValidPassword("abc12345")}")  // true
    println("Username 'jo' valid: ${isValidUsername("jo")}")              // false
    println("Username 'john' valid: ${isValidUsername("john")}")          // true
    
    // Create formatters
    val htmlBold = createFormatter("", "")
    val brackets = createFormatter("[", "]")
    
    println(htmlBold("Important"))  // Important
    println(brackets("Note"))       // [Note]
    
    // Create counter
    val counter = createCounter(10)
    println("Count: ${counter()}")  // 11
    println("Count: ${counter()}")  // 12
    println("Count: ${counter()}")  // 13
}

Output:

Password 'abc123' valid: false

Password 'abc12345' valid: true

Username 'jo' valid: false

Username 'john' valid: true

<b>Important</b>

[Note]

Count: 11

Count: 12

Count: 13

🔹 Common Higher-Order Functions

Kotlin provides many built-in higher-order functions:

fun main() {
    val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    val words = listOf("apple", "banana", "cherry", "date", "elderberry")
    
    // map - transform each element
    val doubled = numbers.map { it * 2 }
    println("Doubled: $doubled")
    
    // filter - select elements that match condition
    val evenNumbers = numbers.filter { it % 2 == 0 }
    println("Even numbers: $evenNumbers")
    
    // reduce - combine all elements into single value
    val sum = numbers.reduce { acc, n -> acc + n }
    println("Sum: $sum")
    
    // fold - like reduce but with initial value
    val product = numbers.fold(1) { acc, n -> acc * n }
    println("Product: $product")
    
    // any - check if any element matches condition
    val hasLongWord = words.any { it.length > 6 }
    println("Has long word: $hasLongWord")
    
    // all - check if all elements match condition
    val allStartWithLetter = words.all { it.isNotEmpty() }
    println("All non-empty: $allStartWithLetter")
    
    // groupBy - group elements by key
    val groupedByLength = words.groupBy { it.length }
    println("Grouped by length: $groupedByLength")
}

Output:

Doubled: [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Even numbers: [2, 4, 6, 8, 10]

Sum: 55

Product: 3628800

Has long word: true

All non-empty: true

Grouped by length: {5=[apple], 6=[banana, cherry], 4=[date], 10=[elderberry]}

🧠 Test Your Knowledge

What makes a function a "higher-order function"?