https://kotlinlang.org logo
#getting-started
Title
# getting-started
k

Klitos Kyriacou

11/29/2023, 11:11 AM
Is it possible to have partial inference? I've got something like:
Copy code
inline fun <K, reified V> Map<out K, *>.filterValueIsInstance(): Map<K, V>
and it needs to be called like this:
Copy code
mapOf('i' to 1, 'j' to 2, 'l' to 3L, 's' to 4.toShort()).filterValueIsInstance<Char, Int>()  // == mapOf('i' to 1, 'j' to 2)
Is it possible to define it in such a way that the compiler infers what type the keys are, and just needs the target type, like this:
Copy code
mapOf('i' to 1, 'j' to 2, 'l' to 3L, 's' to 4.toShort()).filterValueIsInstance<Int>()  // == mapOf('i' to 1, 'j' to 2)
j

Javier

11/29/2023, 11:22 AM
The only way is creating a
filterValueIsInstance
which has only a type parameter. Have you tried something like
Copy code
inline fun <reified V> Map<*, *>.filterValueIsInstance(): Map<*, V>
y

Youssef Shoaib [MOD]

11/29/2023, 11:30 AM
I wish that was possible. The closest you can get is:
Copy code
myMap.filterValueIsInstance<_, Int>()
thank you color 1
t

Tomer Arazy

11/30/2023, 9:09 AM
You can do:
inline fun <K, reified V : Any> Map<out K, *>.filterValueIsInstance(c: KClass<V>): Map<K, V>
And then call it like:
mapOf('i' to 1, 'j' to 2, 'l' to 3L, 's' to 4.toShort()).filterValueIsInstance(Int::class)
I'm not a big fan of this syntax but don't think there is a better alternative.
k

Klitos Kyriacou

11/30/2023, 9:18 AM
Interesting, thanks. And if you have a default parameter value –
(c: KClass<V> = V::class)
– then the caller has a choice of syntax. 😀
🙌 1
y

Youssef Shoaib [MOD]

11/30/2023, 12:50 PM
If you do it that way, then you might want to use a lighter-weight way to carry around the type. I've used this pattern before the
_
existed for inferring type arguments:
Copy code
fun main() {
    mapOf('i' to 1, 'j' to 2, 'l' to 3L, 's' to 4.toShort()).filterValueIsInstance(type<Int>())
}
inline fun <K, reified V> Map<out K, *>.filterValueIsInstance(type: TypeWrapper<V> = type()): Map<K, V> = TODO()

sealed interface TypeWrapper<out T> {
    companion object IMPL: TypeWrapper<Nothing>
}

fun <T> type(): TypeWrapper<T> = TypeWrapper.IMPL
j

Javier

11/30/2023, 12:54 PM
Why not just
filterValueIsInstance<Int>()
?
y

Youssef Shoaib [MOD]

11/30/2023, 12:56 PM
@Javier because we want to preserve the key type of the map.
👍 1