samir
11/02/2018, 11:07 AMval imap = mapOf("a" to "a")
// val mmap = imap as MutableMap
imap["b"] = "b" //compiler error
val imap = mapOf("a" to "a")
val mmap = imap as MutableMap
imap["b"] = "b" //runtime error java.lang.UnsupportedOperationException
Denis A
11/02/2018, 11:11 AMEgor Trutenko
11/02/2018, 11:12 AMmmap
? What is it for?arve
11/02/2018, 11:34 AMval imap = mapOf("a" to "a")
imap as MutableMap // Won't compile if i remove this
imap["b"] = "b" // Compiles just fine, but obviously runtime error
seems like as
acts more like a statement than an expression 🤔Egor Trutenko
11/02/2018, 11:38 AMas
is a pure expression - it returns a value of another type, it does not modify existing one. It is pretty much impossible. It is supposed to work like this:
val imap = mapOf("a" to "a")
val mmap = imap as MutableMap
mmap["b"] = "b" // works
arve
11/02/2018, 11:41 AMJakub Aniola
11/02/2018, 11:42 AMval mmap: MutableMap = mapOf("a" to "a")
mmap["b"] = "b" // also works
Egor Trutenko
11/02/2018, 11:44 AMimap as MutableMap
(even though it did not have obvious effects) you presumed that imap
is actually mutable and compiler took it for granted.arve
11/02/2018, 11:45 AMEgor Trutenko
11/02/2018, 11:45 AMarve
11/02/2018, 11:46 AMas
is supposed to be an expressionEgor Trutenko
11/02/2018, 11:48 AMuhe
11/02/2018, 11:57 AMgildor
11/02/2018, 12:12 PMMutableMap
doesn’t exist on Java side and will be replaced with java’s Map interface (every map is “mutable” on Java side from types point of view)
So Kotlin mapOf function returns instance of SingletonMap which is immutable, than you cast it to Map inteface (which is valid cast), so Smartcast now sure that this type is MutableMap, but when you call “SingletonMap.put” UnsupportedOperationException will be thrown on runtimesamir
11/02/2018, 12:20 PMimap as MutableMap
should not change imap.Egor Trutenko
11/02/2018, 12:21 PMSingletonMap
. That's the issue as wellimap
is left intact after as
, but smartcast system thinks that now you can use imap
as MutableMap
, because you already assumed that it is MutableMap
.MutableMap
overrides Map
samir
11/02/2018, 12:23 PMEgor Trutenko
11/02/2018, 12:24 PMsamir
11/02/2018, 12:29 PMgildor
11/02/2018, 12:31 PMsamir
11/02/2018, 12:33 PMgildor
11/02/2018, 12:37 PMEgor Trutenko
11/02/2018, 1:27 PMgildor
11/02/2018, 1:27 PMEgor Trutenko
11/02/2018, 1:42 PMmapOf
behavior (though, this is actually impossible now) for it not to return SingletonMap
. You also can't throw ClassCastException
, because casts are not broken. There is required a total reimagining either of the whole collections-related things or of the type system. Or it's just to accept that mapOf/1
, listOf/1
etc. work that way and from time to time explain it. But imho it's still rather silly that one of the most usable languages has such issuegildor
11/02/2018, 1:43 PMwhat is it to be done apart from changingI don’t understand how this somehow help? You still have any other implementations of Map, not only in Kotlin, any method can return you kotlin.Map and it can be any typebehavior (though, this is actually impossible now) for it not to returnmapOf
SingletonMap
Egor Trutenko
11/02/2018, 1:47 PMmapOf
to MutableMap
, which will result in notorious behavior. Yes, there's a bigger problem of Java interop, but you usually don't encounter it because you work with types you are aware of.samir
11/02/2018, 1:48 PMimap
-> compiler error.Egor Trutenko
11/02/2018, 1:50 PMalso why anyone would cast type to MutableMap?Don't ask me, I never use mutable collections :^D But such questions and issues come up, right? Meaning some people, at least initially, suffer from it
gildor
11/02/2018, 1:58 PMdon't encounter it because you work with types you are aware of.What do you mean?
samir
11/02/2018, 2:03 PMmmap
execute put but not when imap
does itEgor Trutenko
11/02/2018, 2:03 PMClassCastException
is better? I explicitly said that it is nowhere to be thrown, nor there is the reason for itsamir
11/02/2018, 2:03 PMimap as MutableMap
statement changes compiler behavior on imap
feels error prone.gildor
11/02/2018, 2:03 PMEgor Trutenko
11/02/2018, 2:04 PMHow you can accidentally cast somethingAnd still you get runtime exception from something that you expect not to fail
gildor
11/02/2018, 2:05 PMI explicitly said that it is nowhere to be thrown, nor there is the reason for itWhy? This is implementation detail only. Next version of Kotlin can return immutable map always
Egor Trutenko
11/02/2018, 2:07 PMMap
existing in runtime, you can't (probably can't) fix it by adding or changing interfacesgildor
11/02/2018, 2:07 PMCasting collection is error prone in any case. Kotlin just couldn't protect you from using existing Java APIs in a wrong waystatement changes compiler behavior onimap as MutableMap
feels error prone.imap
Egor Trutenko
11/02/2018, 2:15 PMgildor
11/02/2018, 2:17 PMEgor Trutenko
11/02/2018, 2:18 PMgildor
11/02/2018, 2:18 PMEgor Trutenko
11/02/2018, 2:18 PMgildor
11/02/2018, 2:19 PMEgor Trutenko
11/02/2018, 2:21 PMmapOf
, like, what?
Again, apart from the fact that it's not really smart to cast maps to mutable maps. There are circumstances and there are people with Java background, who haven't yet got used to immutable collectionsgildor
11/02/2018, 2:26 PMEgor Trutenko
11/02/2018, 2:27 PMgildor
11/02/2018, 2:27 PMEgor Trutenko
11/02/2018, 2:28 PMThis is price that you pay to have great Java interop and performance