Hi, can anyone explain why in this code: ```fun Li...
# getting-started
j
Hi, can anyone explain why in this code:
Copy code
fun List<User>.aggregate(): List<User> {
    val result = this
        .groupingBy { it.login } // Grouping<User, String>
        .aggregate { key: String, accumulator: User?, element: User, first: Boolean
            ->
            if (first) element
            else User(
                accumulator!!.login,
                accumulator!!.contributions + element.contributions
            )
        }
    return result.values.toList()
}
result
’s type becomes
Map<String, User?>
, while I was expecting it to be
Map<String, User>
?
j
Your accumulator has type User? which can be null. It's why you are doing the !! coercion, but remember that the result of the lambda passed to aggregate is still User? which is eventually collected into a Map<Int, User?> The signature on https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/aggregate.html is misleading. It really does return Map<K, R*?*> even in the example given on that page. When I explicitly set the the type, the check fails only at runtime possibly due to inlining?
Copy code
val numbers = listOf(3, 4, 5, 6, 7, 8, 9)

    val aggregated : Map<Int, StringBuilder> = numbers.groupingBy { it % 3 }.aggregate { key, accumulator: StringBuilder?, element, first ->
        if (first) // first element
            StringBuilder().append(key).append(":").append(element)
        else
            accumulator!!.append("-").append(element)
    }
Above code fails at runtime unless the type of aggregated is set to Map<Int, StringBuilder*?*> Looks like a bug to me.
My first paragraph above is wrong, the return type of the lambda should be a non-null type, but it's not. Still a bug.
It's a compiler bug but you can work around it by explicitly specifying the type parameters on aggregate:
Copy code
fun List<User>.aggregate(): List<User> {
    val result = this
        .groupingBy { it.login } // Grouping<User, String>
        .aggregate<User, String, User> { key: String, accumulator: User?, element: User, first: Boolean
            ->
            if (first) element
            else User(
                accumulator!!.login,
                accumulator!!.contributions + element.contributions
            )
        }
    return result.values.toList()
}
👍 1
j
I see. Thank you for the information!