Kotlin Higher-Order Functions and Lambdas: Function Types, Inline Functions & Properties

1. What are higher-order functions in Kotlin?

Higher-order functions are functions that take other functions as parameters or return functions as results. They enable functional programming paradigms, promoting code reusability and abstraction.

Key features:

Use Case: Processing collections, event handling, or chaining operations.

2. How do you define and use higher-order functions?

Syntax:

fun higherOrder(param: (Int) -> Int): Int {
    return param(5)
}
      

Lambda: (input: Type) -> Output.

3. Can you give an example of higher-order functions?

fun applyOperation(x: Int, operation: (Int) -> Int): Int {
    return operation(x)
}

fun main() {
    // Using lambda as parameter
    val doubled = applyOperation(10) { it * 2 }
    val squared = applyOperation(10) { it * it }
    
    println("Doubled: $doubled")
    println("Squared: $squared")
    
    // Function reference as parameter
    val tripled = applyOperation(10, ::triple)
    println("Tripled: $tripled")
}

fun triple(x: Int): Int = x * 3
      

Output:

Doubled: 20
Squared: 100
Tripled: 30
      

Note:

4. What are lambda expressions in Kotlin?

Lambda expressions are anonymous functions defined inline, used as arguments or returned values. They are concise and essential for higher-order functions.

Syntax: { parameters -> body }.

Trailing Lambda: If the last parameter, lambda can be passed outside parentheses.

Use Case: Filtering collections, event listeners.

5. Can you give an example of lambda expressions?

val numbers = listOf(1, 2, 3, 4, 5)

// Filter with lambda
val evens = numbers.filter { it % 2 == 0 }
println("Even numbers: $evens")

// Map with lambda
val squared = numbers.map { it * it }
println("Squared numbers: $squared")

// Trailing lambda
val names = listOf("Krishna", "Ram", "Charlie")
val longNames = names.filter { it.length > 4 }
println("Long names: $longNames")
      

Output:

Even numbers: [2, 4]
Squared numbers: [1, 4, 9, 16, 25]
Long names: [Krishna, Charlie]
      

Note:

6. What are function types and references in Kotlin?

7. Can you give an example of function types and references?

fun processString(input: String, transformer: (String) -> String): String {
    return transformer(input)
}

fun upperCase(s: String): String = s.uppercase()
fun reverse(s: String): String = s.reversed()

fun main() {
    // Using function reference
    val result1 = processString("Hello", ::upperCase)
    println("Uppercase: $result1")
    
    // Using lambda
    val result2 = processString("Hello", { it.reversed() })
    println("Reversed: $result2")
    
    // Function type
    val custom: (String) -> String = { it.lowercase() }
    val result3 = processString("HELLO", custom)
    println("Lowercase: $result3")
}
      

Output:

Uppercase: HELLO
Reversed: olleH
Lowercase: hello
      

Note:

8. What are inline functions in Kotlin?

Inline functions, annotated with inline, substitute lambda code at the call site to avoid function call overhead.

Benefits: Improves performance for higher-order functions with lambdas.

Syntax: inline fun functionName(lambda: () -> Unit) { ... }.

Use Case: Optimizing lambda-heavy code.

9. Can you give an example of inline functions?

inline fun  measureTime(block: () -> T): T {
    val start = System.currentTimeMillis()
    val result = block()
    val end = System.currentTimeMillis()
    println("Time: ${end - start} ms")
    return result
}

fun main() {
    // Using inline function
    val result = measureTime {
        var sum = 0
        for (i in 1..1000000) {
            sum += i
        }
        sum
    }
    println("Result: $result")
}
      

Output (Sample):

Time: 45 ms
Result: 500000500000
      

Note:

10. What are higher-order properties in Kotlin?

Higher-order properties are properties that hold functions, similar to higher-order functions but for storing callable objects.

Syntax: var property: (Type) -> ReturnType = { ... }.

Use Case: Storing callbacks or strategies in properties.

Note: Less common than higher-order functions but useful for configuration.

11. Can you give an example of higher-order properties?

class Calculator {
    var operation: (Int, Int) -> Int = { a, b -> a + b }
    
    fun calculate(a: Int, b: Int): Int {
        return operation(a, b)
    }
}

fun main() {
    val calc = Calculator()
    
    // Default: addition
    println("Add: ${calc.calculate(5, 3)}")
    
    // Change property to multiplication
    calc.operation = { a, b -> a * b }
    println("Multiply: ${calc.calculate(5, 3)}")
    
    // Change to subtraction
    calc.operation = { a, b -> a - b }
    println("Subtract: ${calc.calculate(5, 3)}")
}
      

Output:

Add: 8
Multiply: 15
Subtract: 2
      

Note:

12. Can you provide a comprehensive example of higher-order functions and properties?

class DataProcessor {
    var validator: (String) -> Boolean = { it.isNotEmpty() }
    var transformer: (String) -> String = { it.uppercase() }
    
    fun processData(input: String, processor: (String) -> String): String {
        if (!validator(input)) {
            throw IllegalArgumentException("Invalid input: $input")
        }
        return processor(input)
    }
    
    inline fun  timedOperation(operation: () -> T): T {
        val start = System.currentTimeMillis()
        val result = operation()
        val end = System.currentTimeMillis()
        println("Operation took ${end - start} ms")
        return result
    }
}

fun main() {
    val processor = DataProcessor()
    
    // Using higher-order function
    val result1 = processor.processData("hello", processor.transformer)
    println("Processed: $result1")
    
    // Using lambda in higher-order function
    val result2 = processor.processData("world", { it.reversed() })
    println("Reversed: $result2")
    
    // Changing property
    processor.validator = { it.length > 3 }
    processor.transformer = { it.lowercase() }
    
    // Using inline higher-order function
    val result3 = processor.timedOperation {
        processor.processData("kotlin", processor.transformer)
    }
    println("Timed: $result3")
    
    // Error handling
    try {
        processor.processData("hi", { it.uppercase() })
    } catch (e: IllegalArgumentException) {
        println("Error: ${e.message}")
    }
}
      

Output (Sample):

Processed: HELLO
Reversed: dlrow
Operation took 0 ms
Timed: kotlin
Error: Invalid input: hi
      

Description:

13. What are common mistakes in higher-order functions and properties?

Higher-Order Functions:

Lambda Expressions:

Function Types/References:

Inline Functions:

Higher-Order Properties:

General:

14. What are best practices for higher-order functions and properties?

Higher-Order Functions:

Lambda Expressions:

Function Types/References:

Inline Functions:

Higher-Order Properties:

General: