Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

413
Views
Kotlin Problem Delegating to Map with DefaultValue - Language Bug?

In the following code, where MyMap trivially implements Map by delegation to impl:

foo@host:/tmp$ cat Foo.kt
class MyMap <K, V> (val impl : Map <K, V>) : Map<K, V> by impl {
  fun myGetValue (k: K) = impl.getValue(k)
}

fun main() {
  val my_map = MyMap(mapOf('a' to 1, 'b' to 2).withDefault { 42 })
  println(my_map.myGetValue('c'))  // OK
  println(my_map.getValue('c'))    // ERROR
}

Why do I get the following error on the second println?

foo@host:/tmp$ /path/to/kotlinc Foo.kt
foo@host:/tmp$ /path/to/kotlin FooKt
42
Exception in thread "main" java.util.NoSuchElementException: Key c is missing in the map.
        at kotlin.collections.MapsKt__MapWithDefaultKt.getOrImplicitDefaultNullable(MapWithDefault.kt:24)
        at kotlin.collections.MapsKt__MapsKt.getValue(Maps.kt:344)
        at FooKt.main(Foo.kt:8)
        at FooKt.main(Foo.kt)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.jetbrains.kotlin.runner.AbstractRunner.run(runners.kt:64)
        at org.jetbrains.kotlin.runner.Main.run(Main.kt:176)
        at org.jetbrains.kotlin.runner.Main.main(Main.kt:186)
foo@bigdev:/tmp$

Update: The compiler and runtime version outputs are:

foo@host:/tmp$ kotlinc -version
info: kotlinc-jvm 1.6.10 (JRE 17.0.1+12-LTS)
foo@host:/tmp$ kotlin -version
Kotlin version 1.6.10-release-923 (JRE 17.0.1+12-LTS)
foo@host:/tmp$ javac -version
javac 17.0.1
foo@host:/tmp$ java -version
openjdk version "17.0.1" 2021-10-19 LTS
OpenJDK Runtime Environment Corretto-17.0.1.12.1 (build 17.0.1+12-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.1.12.1 (build 17.0.1+12-LTS, mixed mode, sharing)
over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Though I would have expected your code to work to be honest, this could be bug but we'd have to look at the produced bytecode.

In the documentation it says (emphasis mine):

This implicit default value is used when the original map doesn't contain a value for the key specified and a value is obtained with Map.getValue function, for example when properties are delegated to the map.

The conflict of "contracts" comes from the actual Map interface, which says:

Returns the value corresponding to the given [key], or null if such a key is not present in the map.

The maps default contract must fulfill this, so it can "only" return null when a key is non-existent.

I have found one discussion about this in the Kotlin forums.

over 4 years ago · Santiago Trujillo Report

0

This is occurring because of the slightly unexpected way in which withDefault is implemented. The wrapper that withDefault produces doesn't override getValue() as this is impossible because getValue() is an extension function. So unfortunately, what we have instead is a classic OOP anti-pattern: getValue() does an is check to see if it's being called on the internal MapWithDefault interface, and only uses the default value if that is the case. I don't see any way they could have avoided this situation without breaking the Map contract.

myGetValue calls getValue on the underlying delegate, which is a MapWithDefault, so it works fine.

getValue called on your MyMap instance will fail the internal is MapWithDefault check because MyMap is not a MapWithDefault, even though its delegate is. The delegates other types are not propagated up to the class that delegates to it, which makes sense. Like if we delegated to a MutableMap, we might want the class to be considered only a read-only Map.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!