Kotlin Tutoial

Basics

Control Flow

Array & String

Functions

Collections

OOPs Concept

Exception Handling

Null Safety

Regex & Ranges

Java Interoperability

Miscellaneous

Android

Kotlin Higher-Order Functions

In Kotlin, functions are first-class citizens. This means you can store them in variables, pass them as parameters, and return them from other functions. A function that takes another function as a parameter or returns a function is called a higher-order function.

Here's a tutorial on higher-order functions in Kotlin:

1. Basics of Higher-Order Functions:

A simple higher-order function that accepts a function as a parameter:

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

val sum = calculate(3, 4, { a, b -> a + b })  // Result: 7

2. Function Type:

In the above example, (Int, Int) -> Int is a function type that represents a function taking two Int parameters and returning an Int.

3. Returning a Function:

A higher-order function can also return another function:

fun multiplyBy(factor: Int): (Int) -> Int {
    return { number -> number * factor }
}

val double = multiplyBy(2)
println(double(4))  // Result: 8

4. Lambda Expressions:

In Kotlin, a lambda is a short way of representing a function. In the first example, { a, b -> a + b } is a lambda expression.

5. It keyword:

When the lambda has only one parameter, you can use the it keyword:

val numbers = listOf(1, 2, 3, 4)
numbers.filter { it % 2 == 0 }  // Filters even numbers

6. Using Higher-Order Functions with Collections:

Kotlin's standard library provides several higher-order functions like map, filter, forEach, etc.:

val doubled = numbers.map { it * 2 }
val even = numbers.filter { it % 2 == 0 }

7. Inline Functions:

Using higher-order functions can introduce runtime overhead because of the creation of function objects. To mitigate this, Kotlin offers inline functions:

inline fun performOperation(x: Int, y: Int, op: (Int, Int) -> Int): Int {
    return op(x, y)
}

Using the inline keyword instructs the compiler to copy the lambda's code to the calling place, reducing the overhead.

8. Closures:

Lambdas can modify variables from the outer scope:

var sum = 0
numbers.forEach { sum += it }

9. Function References:

You can also pass named functions as arguments if they match the expected type:

fun sum(a: Int, b: Int) = a + b

val result = calculate(5, 3, ::sum)  // Using :: to reference the function

10. Extension Functions as Lambda:

You can use extension functions as lambdas:

val stringList = listOf("Kotlin", "Java", "C++")
val sortedList = stringList.sortedWith(Comparator<String>::length)

Conclusion:

Higher-order functions and lambdas are powerful features of Kotlin. They allow for concise and expressive code, especially when working with collections. They're essential for functional programming styles in Kotlin and provide a flexible way to encapsulate behavior. Familiarizing yourself with these concepts can help in writing clean and efficient Kotlin code.

  1. Passing functions as parameters in Kotlin:

    • Define a higher-order function that takes another function as a parameter.
    fun operation(x: Int, y: Int, op: (Int, Int) -> Int): Int {
        return op(x, y)
    }
    
  2. Returning functions from functions in Kotlin:

    • Return a function from another function.
    fun multiplyBy(factor: Int): (Int) -> Int {
        return { number -> number * factor }
    }
    
  3. Anonymous functions and lambda expressions in Kotlin:

    • Use anonymous functions and lambda expressions.
    val square: (Int) -> Int = { x -> x * x }
    val add: (Int, Int) -> Int = { a, b -> a + b }
    
  4. Function types in Kotlin:

    • Declare function types.
    val operation: (Int, Int) -> Int = { x, y -> x + y }
    
  5. Using higher-order functions with collections in Kotlin:

    • Apply higher-order functions to manipulate collections.
    val numbers = listOf(1, 2, 3, 4, 5)
    val squared = numbers.map { it * it }
    
  6. Higher-order functions vs regular functions in Kotlin:

    • Compare higher-order and regular functions.
    fun add(x: Int, y: Int): Int {
        return x + y
    }
    
    val higherOrderAdd: (Int, Int) -> Int = { a, b -> a + b }
    
  7. Function references in Kotlin:

    • Reference functions using :: syntax.
    val sum: (Int, Int) -> Int = ::add
    
  8. Examples of higher-order functions in Kotlin:

    • Examples of using higher-order functions.
    val numbers = listOf(1, 2, 3, 4, 5)
    val sum = numbers.reduce { acc, value -> acc + value }
    
  9. Functional programming principles in Kotlin:

    • Embrace principles like immutability, pure functions, and higher-order functions.
    val squaredNumbers = numbers.map { it * it }
    
  10. Built-in higher-order functions in Kotlin standard library:

    • Explore built-in higher-order functions in the Kotlin standard library.
    val filteredNumbers = numbers.filter { it % 2 == 0 }
    
  11. Higher-order extension functions in Kotlin:

    • Extend existing types with higher-order functions.
    fun List<Int>.customSum(): Int {
        return this.reduce { acc, value -> acc + value }
    }