18786, "bmcdonald3", "Adding an overload to 'map.getValue()' to avoid halting", "2021-12-02T17:49:00Z"
Summary
The getValue()
map method halts if the value is not found today and this can cause problems in a parallel context, where wrapping the getValue()
check in a if myMap.contains(val)
can still halt if the value has been removed in the time from the contains call and the using of getValue()
. This can be avoided by adding an overload to getValue()
to take a "sentinel" value that will be returned if the value is not found, rather than halting.
Proposed solutions
Proposal 1: Add an overload to getValue()
to return a "sentinel" value
proc map.getValue(key) { ... } // current getValue(), halts if 'key' is not found
proc map.getValue(key, sentinel) { ... } // returns 'sentinel' if the key is not found
Usage:
var value = map.getValue(key, 0) + 1; // never halts; value either 1 or key+1
Proposal 2: Switch to throw instead of halt to allow catching the error
proc map.getValue(key) throws { ... }
Usage:
var value: int;
try {
value = map.getValue(key) + 1;
} catch {
value = 1;
}
Proposal 3: New function that returns a sentinel and boolean false if key not found
(the name would definitely need some rethinking...)
proc map.getValue(key) { ... }
proc map.didGetValue(key, sentinel) { ... }
Usage:
var (value, found) = map.didGetValue(key, 0); // if 'key' not found then 'value'=0 and 'found'=false
Previous discussion
See the original user issue: New argument in map.getValue() · Issue #17498 · chapel-lang/chapel · GitHub
Arguments against proposal 1:
-
getReference
/getBorrowed
don't have as clear of a solution, making some assymetry - the syntax isn't particularly elegant and could be better (e.g.,
var v = try m.getValue(0) else 1;
, but something like this wouldn't work today and would be a bigger change)