in reply to Re: Adding or removing keys while iterating over a hash
in thread Adding or removing keys while iterating over a hash
This is for two reasons. First, unlike insertion, a deletion never causes a complete reorganization of the entire hash. (This is mentioned in the part of the FAQ that you quoted.) But there's also something more subtle going on.
The way a hash works is that it's a collection of lists of he items. Each he has a pointer to a key, to the associated value, and a pointer to the next he in the list. Every hash also keeps track of the 'current' he. When you call each, it advances the 'current item' pointer to the next he. It can do this because each he points at the next one.
Normally, when you call delete, the memory for the deleted he is reclaimed right away. But if you delete the 'current item', there's a complication. If the he were destroyed and the memory were reclaimed right away, then the next time you called each, it wouldn't work, because it needs to find the 'next' item, and the information would have been stored in the he that you destroyed.
So there is special-case code inside the delete function that specifically checks to see if you are deleting the 'current item', and if so, it postpones the destruction of the he until after the next time you call each. There's more special-case code inside of each that checks to see if you already used delete on the current item, and if so, it belatedly destroys the he after advancing the 'current item'.
In other words, Larry went to some special effort to make sure that you could delete nodes inside of an each loop, so it's particularly odd that this isn't documented.
In recognition of this, the Perl 5.6.1 the manual will include the following:
Exception: It is always safe to delete the item most recently returned by each(), which means that the following code will work:But I still don't know why arbitrary deletions are warned against, since they do always work.while (($key, $value) = each %hash) { print $key, "\n"; delete $hash{$key}; # This is safe }
|
|---|