btw. I am slightly puzzled about the design decisi...
# stdlib
r
btw. I am slightly puzzled about the design decision of the underlying
MapWithDefault
interface design, in part exactly due to the things I'm bumping into here. I'm surprised by both the fact that it's
private
- why would one want to prevent a 3rd party to make use of that interface? And secondly why the default value isn't a value on that interface. That could've allowed me to write a wrapper
plusWithValue
or whatever, if it's not already there, and if it's there, there's probably all sorts of other utility functions that could make sense to allow 🙂
e
IMO
MapWithDefault
is only practically usable in situations like
Copy code
val x by map.withDefault { fallback }
anything more than that would require more changes to the rest of the collections api
e.g.
mapWithDefault["x"]
is still nullable,
mapOf("a" to 1).withDefault { 2 } != mapOf("a" to 1, "b" to 2).withDefault { 2 }
, etc.
r
@ephemient I'm curious, why would you assign
x
by a delegate in this situation?
well having the interface public and exposing the assigned default seems quite reasonable to me, then I could at least make my own extension function
plusWithValue
that behaves as desired. Otherwise the API practically enforces mutable maps on me in these situations, and then I'd have to start making all sorts of workarounds to not open the pure hell mutability can be, a simple example:
Copy code
class ClassWithMaps {
  private val _mapOfMaps = mutableMapOf<Key1, Map<Key2, Value>>().withDefault { emptyMap().withDefault { defaultValue } }
  // Hide all mutability and avoiding the  can of worms of values changing while the client does whatever with the map it read
  val mapOfMaps: Map<Key1, Map<Key2, Value>>
      get() = _mapOfMaps.toMap()

  fun modifyMyMap() {
    val key1 = someKey1()
    val entry = someKey2ToValue()

    val currentValue = _mapOfMaps.getValue(key1)
    _mapOfMaps[key1] = currentValue + entry // This breaks the inner withDefault
  }
}
with those exposed I could at least have some kind of extension for this task, or in this case where I know it would always be a
MapWithDefault
do something like:
Copy code
class ClassWithMaps {
  // ..
  
  fun modifyMyMap() {
    // ..

    val currentValue = _mapOfMaps.getValue(key1) as MapWithDefault
    _mapOfMaps[key1] = (currentValue + entry).withDefault { currentValue.defaultValue }
  }
}
a logic which I could further make more readable, by having an extension function or similar