Marc Knaup
12/24/2019, 4:23 PMMap.getOrElseNullable()
not public API?
I’ve just now noticed that .getOrElse()
doesn’t work as documented for null
values.
Returns the value for the given key, or the result of thefunction if there was no entry for the given key.defaultValue
miha-x64
12/24/2019, 4:27 PMget(key) ?: if (containsKey(key)) null else defaultValue
may not work correctly with concurrent collections. But the current implementation is totally wrong and must have V : Any
type parameter bound.Marc Knaup
12/24/2019, 4:33 PMV : Any
would break some code that wants to return V?
in defaultValue
, for example:
map.getOrElse(key) { cache[key] }
Changing the return type of defaultValue
to V?
also won’t work as it’s always nullable then.
I don’t see the issue with concurrent collections 🤔miha-x64
12/24/2019, 4:36 PMget
and containsKey
could return inconsistent values.
get() -> null
other thread: put
containsKey() -> true
got nullmiha-x64
12/24/2019, 4:37 PM: V
for default and return valueMarc Knaup
12/24/2019, 4:54 PMthere could be other type parameterI don’t think Kotlin can model that. You’d needfor default and return value: V
V
to be s subtype of R
and also a subtype of Any
.Marc Knaup
12/24/2019, 4:57 PMget() -> null
other thread: put
containsKey() -> true
got nullSo the only downside is that it would return the default value in a case where some other thread has added a
null
value in the meantime?
I still don’t see how that is an issue. getOrElse()
won’t fare much better. By the time the function has returned another thread may already have added/replaced the value due to lack of proper synchronization.miha-x64
12/25/2019, 7:33 AMadded aAny value.value in the meantimenull
Marc Knaup
12/25/2019, 8:23 AMcontainsKey if get() returned null. So in all
other cases it behaves like the normal getOrElse
.
Woah Slack's message formatting became really annoying recently.miha-x64
12/25/2019, 8:31 AMget()
returns null
when there's no such mapping.
map = {}
map.get(key) -> null
map = {key=value}
map.containsKey(key) -> trueMarc Knaup
12/25/2019, 8:36 AMgetOrElseNullable
doesn't call containsKey
unless get
has returned null
, so how can that lead to a race condition that would be different from a simple get
in getOrElse
?miha-x64
12/25/2019, 8:39 AMMarc Knaup
12/25/2019, 8:43 AMnull
case, yet you've said that it applies for all values, which isn't the case.
And even if there is a race condition like that - I don't see how that is a problem at all since having that get
and containsKey
together in one atomic operation doesn't bring any benefit, since the caller of getOrElseNullable
AND getOrElse
still has race conditions with the map unless there is additional synchronization.
It would be totally different for getOrPut
as that one definitely needs to be atomic since it both reads and writes.Marc Knaup
12/25/2019, 8:52 AMMarc Knaup
12/25/2019, 9:23 AM