Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin smart cast the second value of a pair with filter

Tags:

kotlin

I'm trying to write a function that maps a String and Int? into a pair, then filters for non null second values in the pair, before continuing to map.

My code looks like this:

val ids: List<String> = listOf("a", "b", "c")
val ints: Map<String, Int?> = mapOf("a" to 1, "b" to 2, "c" to null)

ids.map { id: String ->
    Pair(id, ints[id])
}.filter { pair -> pair.second != null}.map { pair: Pair<String, Int> ->
    func(id, pair.second)  
}

The problem is that the second map has the error:

Type inference failed: Cannot infer type parameter T in 
                       inline fun <T, R> kotlin.collections.Iterable<T>.map ( transform (T) -> R ): kotlin.collections.List<R>

This looks like because the compiler does not know to smart cast my Iterable<Pair<String, Int?>> into an Iterable<Pair<String, Int>> after my filter. What can I do instead to solve this?

like image 499
Corey Wu Avatar asked Apr 12 '16 08:04

Corey Wu


1 Answers

Kotlin's smart cast is usually not applicable outside method boundaries. However, there are a couple of ways you can achieve your goal anyway.

First, you can simply tell the compiler that the second value of the pair is never null by using the !! operator like so:

ids.map { id: String -> Pair(id, ints[id]) }
        .filter { pair -> pair.second != null }
        .map { pair: Pair<String, Int?> -> func(pair.second!!) }

Second, you can reverse the order of filter and map and apply the !! operator earlier:

ids.filter { id: String -> ints[id] != null }
        .map { id: String -> id to ints[id]!! } //equivalent to Pair(id, ints[id]!!)
        .map { pair: Pair<String, Int> -> func(pair.second) }

Finally, you can make it work without the !! operator by combining the filtering and the mapping in one step using the mapNotNull extension method:

ids.mapNotNull { id: String -> ints[id]?.let { id to it } }
        .map { pair: Pair<String, Int> -> func(pair.second) }
like image 102
Kirill Rakhman Avatar answered Oct 13 '22 01:10

Kirill Rakhman