**fold()**:

fold() takes an initial value and applies a given operation to each element of the collection, accumulating the result. It requires an initial value to start the accumulation process. Example: Calculating the sum of elements with an initial value of 0:

`collection.fold(0) { acc, element -> acc + element }`

```
val n1 = listOf(6, 3, 11, 5)
val k1 = n1.fold(0){sum, element -> sum + element *2 }
println(k1)
```

output

50

**reduce()** :

reduce() transforms a collection into a single result by applying a specified operation to pairs of elements successively.
It doesn't require an initial value, as it uses the first two elements of the collection for the initial operation.
Example: Calculating the sum of elements:`collection.reduce { acc, element -> acc + element }`

```
val n1 = listOf(6, 3, 11, 5)
val k1 = n1.reduce {sum, element -> sum + element}
println(k1)
```

output

25

Both functions are useful, but fold() provides more flexibility by allowing you to specify an initial value for accumulation, while reduce() assumes the first element as the initial value.

functions reduceRight() and foldRight() work in reverse order. They start from the last element and then continue to previous.

```
val n1 = listOf(6, 3, 11, 5)
val k2 = n1.foldRight(0){element,sum -> sum + element * 2}
println(k2)
```

output

50

There are some function that take element indices as parameters. For this purpose, use functions reduceIndexed() and foldIndexed() passing element index as the first argument of the operation.

reduceRightIndexed() and foldRightIndexed(),are functions that apply such operations to collection elements from right to left

```
val n1 = listOf(6, 3, 11, 5)
val k1 = n1.foldIndexed(0) {idx, sum, element -> if (idx == 0 || idx == 2) sum + element else sum}
val k2 = n1.foldRightIndexed(0) {idx, element, sum -> if (idx == 0 || idx == 2) sum + element else sum}
println(k1)
println(k2)
```

output

17

17