Wrong reduce result with IntRange


#1
fun main() {
    val n = 5
    val X = listOf(1, 2, 3, 4, 5)
    
    val result = (0 until n).reduce { acc, i -> acc + X[i] }
    
    println("--> $result")
}

Why does this code results in 14?


#2

It becomes clear when you print out the actual values:

fun main() {
    val n = 5
    val X = listOf(1, 2, 3, 4, 5)
    
    val result = (0 until n).reduce { acc, i -> 
            println("acc: $acc, i: $i, x: ${X[i]}")
            acc + X[i] 
    }
    
    println("--> $result")
}

Output:

acc: 0, i: 1, x: 2
acc: 2, i: 2, x: 3
acc: 5, i: 3, x: 4
acc: 9, i: 4, x: 5
--> 14

https://pl.kotl.in/BJGyVmySV


#3

Yea. But why `i’ doesn’t point to 0 on the first iteration?


#4

This is the normal behavior of reduce and is also documented. What you are looking for is fold.

(0 until n).fold(initial = 0) { acc , i -> acc + X[i] } 

Because then you couldn’t use the 0-element as the starting value for the accumulator.


#5

I think what you’r looking for is this:

val result = X.reduce { acc, i -> acc + i }

#6

At the first iteration of reduce the lambda is called with the initial value of acc equal to the first element and i equal to the second element. Therefore acc = 0, and i = 1.


#7

Thanks. That’s what I’m looking for.