acando86
12/16/2020, 2:34 PMfun minimalExample(
ids : List<Long>,
details : Map<String, Boolean>
) : List<Boolean?> =
ids.map { id -> details.get(id) }
I'm mapping over a list of Longs
and for each Long
i try to access the corresponding value from a key-value map; the map however here is of type Map<String, Whatever>
, not Map<Long, Whatever>
I've done that on purpose so that when writing details.get(id)
the types don't match
I would have expected the compiler to throw a compilation error, something like type mismatch: inferred type is Long but String was expected
Instead i can compile the code and run it (obviously at runtime there is jvm type erasure on generic and details.get(id) will always return null in this case).
there is a warning
warning: type inference failed. The value of the type parameter K should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly.
the problem with this warning is two fold: 1. it's error prone. I can handle all warnings as errors, or set a linter, but i would have expected the inference to work just fine in this example 2. there seems to be no obvious way to me to provide the extra information that the compiler would need in order for the type inference to work.
is this behaviour expected or is an issue?Marc Knaup
12/16/2020, 2:51 PMfun minimalExample(
ids: List<Long>,
details: Map<String, Boolean>,
): List<Boolean?> =
ids.map { id -> details.get<Any,Boolean>(id) }
acando86
12/16/2020, 3:11 PMAny
is not what's expected here, the map is <String,Boolean>
and the get should be <String, Boolean>
. Writing explicitly Any
is equivalent to not write the types specifically, because that's what the compiler is going to infer anyway. #2 was about restoring type safety in a meaningful way in this example.Marc Knaup
12/16/2020, 3:13 PMget()
is merely Object
, i.e. Any
.acando86
12/16/2020, 3:17 PMmap{ ..}
over listMarc Knaup
12/16/2020, 3:19 PMmap
operator.
fun minimalExample(
ids: List<Long>,
details: Map<String, Boolean>,
): List<Boolean?> =
listOf(details.get(2))
Marc Knaup
12/16/2020, 3:19 PMacando86
12/16/2020, 3:20 PMdetails.get(2)
noMarc Knaup
12/16/2020, 3:20 PMfun minimalExample(details: Map<String, Boolean>): Boolean? =
details.get(2)
acando86
12/16/2020, 3:33 PMval aMap : Map<String, Boolean> = mapOf()·¬
¬
val x : Boolean? = aMap.get(true)¬
This also compiles (with the type inference warning).. Maybe i'm too used to scala/haskell type safety, but as a person that relies a lot on the compiler to spot these issues i was really surprised to discover that access to the elements of a map is actually not so type safe. It might be linked to interoperability with java collections then, but in that case the fact that Map<T,V> is parametrised over two types is kinda misleadingMarc Knaup
12/16/2020, 3:36 PMMarc Knaup
12/16/2020, 3:39 PMMap<*,*>
(cannot call .get()
there without that workaround) or things like Map<out Something, *>
.alllex
12/16/2020, 3:40 PMalllex
12/16/2020, 3:48 PMacando86
12/16/2020, 3:55 PM