#getting-started
Title
# getting-started
e

evkaky

05/20/2021, 10:10 AM
Hello everyone. I was quite surprised that the following code doesn’t get compiled
Copy code
``````val map = mutableMapOf("key1" to 1)
map["key1"] += 2``````
Why Is it not possible to use increment in such a way?
👀 3
h

hho

05/20/2021, 10:19 AM
``map["key1"]``
gives you an instance of
``Int``
, which is immutable. You can't assign a new value to an
``Int``
.
e

evkaky

05/20/2021, 10:21 AM
😭
r

Roukanken

05/20/2021, 10:30 AM
for it to work, you would need to have implemented
``Int?.plusAssign(Int)``
because it does not desugar into
``map.get(a) = map.get(a) + b``
but into
``map.get(a).plusAssign(b)``
h

hho

05/20/2021, 10:33 AM
r

Roukanken

05/20/2021, 10:33 AM
and yes,
``get(a)``
returns nullable, so that's another issue there 😛
u

Ulrik Rasmussen

05/20/2021, 11:44 AM
You could do
``m.compute("key1") { _, i -> i?.let { it + 1 } }``
Or simpler,
``m.computeIfPresent("key1") { _, i -> i + 1 }``
e

evkaky

05/20/2021, 11:47 AM
yeah, seems like this is the most clean solution @Ulrik Rasmussen btw, Swift allows such a code
Copy code
``map["key1"]! += 2``
u

Ulrik Rasmussen

05/20/2021, 11:48 AM
I don't know Swift, but it probably has a more baked in notion of maps. In Kotlin,
``map[k]``
is just sugar for
``map.get(k)``
t

Travis Griggs

05/20/2021, 4:42 PM
Re Swift, I don't think it's the baked in nature of maps, it's that maps are structs in Swift. So the swift analog to OP's query actually would fail in Swift as well. In Swift, val becomes let (simplisitically) speaking, which would mean the struct was immutable. But once it was a var, it would be inherently mutable and would then work
e

ephemient

05/20/2021, 6:06 PM
if there were an API like
Copy code
``fun <K, V> MutableMap<K, V>.findEntry(key: Key): MutableMap.MutableEntry<K, V>?``
then you could
Copy code
``m.findEntry("key1")?.let { it.setValue(it.value + 2) }``
but sadly there is no such API
u

Ulrik Rasmussen

05/21/2021, 6:38 AM
Something like this can be obtained via lenses though: https://arrow-kt.io/docs/optics/at/
m

Michael Böiers

05/21/2021, 2:58 PM
Something else you could do:
Copy code
``````fun <K, V> MutableMap<K, V>.replace(key: K, value: (V) -> V) =
compute(key) { _, old -> if (old == null) null else value(old) }

val map = mutableMapOf("a" to 42)
map.replace("a") { it + 1 }
println(map)``````
e

ephemient

05/21/2021, 3:22 PM
computeIfPresent as mentioned earlier would be better than compute since you're ignoring the absent case
m

Michael Böiers

05/21/2021, 3:30 PM
Yes, correct. I‘d still define an extension function to get rid of the unused function parameter.
Copy code
``````fun <K, V> MutableMap<K, V>.replace(key: K, value: (V) -> V) =
computeIfPresent(key) { _, old -> value(old) }

val map = mutableMapOf("a" to 42)
map.replace("a") { it + 1 }``````