activedecay
activedecay

Reputation: 10847

Type inference for lambda parameter types

Kotlin fails to compile this code because, as the compiler states "Error: Smart cast to 'Nothing' is impossible, because 'accumulator' is a complex expression"

Ye olde function is called what you'd expect, i.e., I want to return the indexOfMax -- but what's more important is understanding why the "smart cast" failed to cast to accumulator an Int

fun indexOfMax(a: IntArray): Int? {
    return a.foldIndexed(null) { index, accumulator, element ->
        return if (accumulator is Int) {
            var i:Int = accumulator
            return if (accumulator == null) index
                   else if (element > a[i]) index
                   else accumulator
        } else accumulator
    }
}

edit

yes, the accepted answer works! Here's the solution:

fun indexOfMax(a: IntArray): Int? {
    return a.foldIndexed(null as Int?) { index, accumulator, element ->
        if (accumulator == null) index
            else if (element >= a[accumulator]) index
            else accumulator
    }
}

Upvotes: 1

Views: 669

Answers (1)

Ilya
Ilya

Reputation: 23115

The type of accumulator here is inferred only from the initial value argument, which is null. That null has type Nothing?. After checking that the type of accumulator is Int, you get its type smartcasted to the intersection of Nothing? and Int, which results in Nothing.

The solution here is to specify either the function type parameters explicitly, or to specify the type of the argument:

a.foldIndexed(null as Int?) { ...
// or
a.foldIndexed<Int?>(null) { ...

Upvotes: 5

Related Questions