Closed
Description
There is no way to clear a map in Go. You can write
for k := range m {
delete(m, k)
}
but that only works if m does not contain any key values that contain NaNs.
Based on the discussion in #55002, we suggest adding delete(m)
to the language to clear the map, always (even if it contains NaNs).
This is somewhat a reopening of #45328, which we closed because the loop was good enough, but we missed the earlier discussion in that issue of NaNs.
Adding delete(m) would then let us also add a similar mechanism in reflect.
We wouldn't need to add maps.Clear(m) since delete(m) is just as good.
Metadata
Metadata
Assignees
Type
Projects
Relationships
Development
No branches or pull requests
Activity
rsc commentedon Oct 20, 2022
This proposal has been added to the active column of the proposals project
and will now be reviewed at the weekly proposal review meetings.
— rsc for the proposal review group
atdiar commentedon Oct 20, 2022
Personally, I'm ok with it but can't determine if it is good enough.
Having a way to disallow NaN containing values in maps would be best. Then map clearing via iteration just works and the change in this proposal is unnecessary (if not for perf reasons).
Otherwise, comparing two maps may still have edge cases. (the crux of the issue is that comparison is actually underspecified it seems).
Notably relevant for Set types that would be implemented by using maps.
With this proposal, map clearing gets solved but not inadvertent comparison of potential NaN composites.
If deemed a serious issue, I'm a bit concerned that it could actually hide a programming mistake instead.
Other than that, this proposal should be semantically sound at least.
robpike commentedon Oct 20, 2022
I tend to agree that this is really only about NaNs, and is a peculiar response to their presence. At least, if you want to justify a new predefined function with a new capability, making NaNs the selling point is off-key (see what I did there?).
earthboundkid commentedon Oct 20, 2022
I worry that this could lead to programmer error when clearing
map[string]map[string]T
ormap[string]any
.timothy-king commentedon Oct 20, 2022
With
delete(m)
, will it be clear whether this is releasing memory of the underlying map?If it does release the memory, it is equivalent to[edit: I was not thinking through aliasing enough.]if m != nil { m = make(m[K]V) }
. (But maybe I am not thinking through aliasing enough?)bcmills commentedon Oct 20, 2022
@atdiar
I think this proposal strictly improves the situation for irreflexive keys: if you use it it does the right thing for clearing the map, and if you don't use it you're no worse off than if it never existed.
That said, this still wouldn't help use-cases that need to add and remove individual keys:
delete(m)
would only give an all-or-nothing approach, where in order to delete an irreflexive key you must burn the rest of the map to the ground along with it.The programming mistake I'm more worried about is typos. If both
delete(m, k)
anddelete(m)
are defined, then I could inadvertently writedelete(m)
when I meantdelete(m, k)
, and they're visually similar enough that the bug could be difficult to spot. 😅randall77 commentedon Oct 20, 2022
I would assume this does not release the memory, just as the delete-with-a-for-loop doesn't.
If we ever implement #20135 the map will shrink eventually if it is never refilled.
Merovius commentedon Oct 20, 2022
@carlmjohnson To be clear, what's the programming error? Both of these would work fine ISTM. For the first I can see that perhaps a programmer might've thought it deletes the inner maps (though that seems a bit far-fetched to me). But the second?
@timothy-king
You are not.
func Clear[K , V](m map[K, V]) { m = make(m[K]V) }
is a NOP, butfunc Clear[K, V](m map[K, V]) { delete(m) }
is not.What's the misuse? Semantics don't change. I am opposed to specify allocation behavior. That's an optimization that's up to implementers.
148 remaining items