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