-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
spec: clarify that modifying map elements in place while iterating is legal #9926
Comments
It's legal. The spec needs to call out addition and removal because it's
not otherwise
clear how addition and removal interact with the range loop.
I don't think the spec needs to say modifying existing value is ok, because
if add/delete
are allowed, there is no way modification isn't allowed (you can always
remove and then
add again)
|
I'm not sure that "adding and removing are safe" strictly implies "modifying in place is safe", but okay. Like I said, it seems natural to assume. But more importantly, the spec doesn't actually say that removing the current entry is legal. It says only "entries that have not yet been reached". So my reading is that even this code, which only removes, is not guaranteed to be legal: var m map[string]int
[...]
for k, _ := range m {
delete(m, k)
} Again this may be because the intent is only to specify what would happen in a situation where it's not clear whether the values would be produced or not. But that still leaves open the question of whether it is safe to remove/modify the current entry. You could for example imagine a map implementation that involves a linked list, where the unlink operation sets the |
the spec only documents what needs to be documented.
In the case of range loops, it's the interaction between add/deletion and
the loop and whether an added/deleted item will be iterated (again).
A lot of things are just implicit and you can't actually document all the
cases anyway (for example, does it need to mention that map assignment
could fail if the process runs out of memory?)
|
I think the key to understanding this is to realize that while executing the body of a for/range statement, there is no current iteration. There is a set of values that have been seen, and a set of values that have not been seen. While executing the body, one of the key/value pairs that has been seen--the most recent pair--was assigned to the variable(s) of the range statement. There is nothing special about that key/value pair, it's just one of the ones that has already been seen during the iteration. I think that once you understand that the meaning of any operation involving the "current" entry is clear. |
@ianlancetaylor: I see, thank you for explaining. |
The spec implies that adding to and removing from maps while iterating is legal by defining the semantics of doing so:
As far as I can tell though, it doesn't explicitly specify that existing keys may be modified but not removed. For example:
Is the above program guaranteed to be legal? Given the strong guarantees on adding and removing elements it seems natural to assume it would be, but explicit clarification from the spec might be good.
The text was updated successfully, but these errors were encountered: