In the previous part, we learned about the basics of functional programming and why it's beneficial to use it. In this part, we will dive deeper into the concepts that will allow you to use functional programming in Kotlin.

Let's start with the Higher-Order Functions

### Higher-Order Functions

In Kotlin, functions are first-class citizens, which means we can use them just like any other value. We can pass functions as arguments to other functions, return functions from functions, and even store functions in variables. The functions that can receive a function as an arugment are called **high-order functions**.

Here's an example of a higher-order function:

```
fun performOperation(x: Int, y: Int, operation: (Int, Int) -> Int): Int {
return operation(x, y)
}
fun add(x: Int, y: Int) = x + y
val result = performOperation(10, 5, ::add)
println(result) // Output: 15
```

In this example, we define a function `performOperation`

that takes two integer arguments `x`

and `y`

, and a third argument `operation`

which is a function that takes two integers and returns an integer. The `performOperation`

function applies the `operation`

function to `x`

and `y`

and returns the result.

We also define a function `add`

that takes two integers and returns their sum. Finally, we call `performOperation`

with `10`

, `5`

, and a reference to the `add`

function using the double colons syntax `::add`

.

### How to use a function

In Kotlin, there are several ways to define and use functions, including lambda functions, anonymous functions, and function references. While all three of these options allow you to pass functions as arguments and return values, they differ in syntax and behavior.

### Lambda functions

Lambda functions are defined using the "->" syntax and are commonly used in functional programming to create higher-order functions. For example, consider the following code:

```
val numbers = listOf(1, 2, 3, 4, 5)
val sum = numbers.reduce { acc, i -> acc + i }
println(sum) // Output: 15
```

For more info about Lambda functions you can head to the official documentation

### Anonymous Functions

Anonymous functions are another way to define functions in Kotlin. They are similar to lambda functions, but they use the `fun`

keyword instead of the `->`

syntax. For example:

```
val numbers = listOf(1, 2, 3, 4, 5)
val sum = numbers.reduce(fun(acc, i): Int {
return acc + i
})
println(sum) // Output: 15
```

Here, we define an anonymous function as the argument to `reduce`

. The anonymous function takes the same arguments and returns the same result as the lambda function in the previous example, but it has a more verbose syntax.

With the anonymous function you can specify the type of the returned value, something that you cannot do with the lambda functions, as this will be deduced by the type inference.

Lambda expressions and anonymous functions differ in their behavior of non-local returns. If we use the `return`

statement without a label, it will always return from the function declared with the `fun`

keyword. This means that if we use `return`

inside a lambda expression, it will return from the enclosing function. However, if we use `return`

inside an anonymous function, it will return from the anonymous function itself.

### Function References

Finally, function references allow you to refer to an existing function by name, without having to define a new function. For example:

```
fun sum(a: Int, b: Int) = a + b
val numbers = listOf(1, 2, 3, 4, 5)
val totalSum = numbers.fold(0, ::sum)
println(totalSum) // Output: 15
```

In this example, we define a function `sum`

that takes two integers and returns their sum. Then, we use the `::`

syntax to pass the function reference to the `fold`

function, which applies it to each element of the list.

### Wrapping up

In summary, lambda functions, anonymous functions, and function references all allow you to define and pass functions as arguments in Kotlin. Lambda functions are the most concise and commonly used option for higher-order functions, while anonymous functions provide a more verbose syntax. Function references allow you to refer to existing functions by name, without having to define new functions.

See you next time!