From: Phrogz Date: 2009-02-16T08:32:53+09:00 Subject: Re: Iterating a changing Hash under 1.9.1 On Feb 15, 8:35 am, Pit Capitain wrote: > 2009/2/15 David A. Black : > > > On Sun, 15 Feb 2009, Phrogz wrote: > >> (...) > > I think modifying a collection while iterating over it is undefined. Ah, doggone it, that was my third choice between "is it a bug or is it not". And I kept saying to myself as I wrote that up "Remember, you should never claim something is a bug unless you're really really sure." I'll accept this answer as reasonable, though it seems a bit of a shame. Always relegating deletions to a delete_if or reject or explicit calls while iterating a duplicate may be inefficient in some cases where complex logic needs to happen and ideally happen in a single pass through the data. It's 'safest' to say "DON'T TRUST ANYTHING, EVER", but provides the lest flexibility during coding. It's most dangerous to say "YOU CAN EXPLOIT WHATEVER IMPLEMENTATION QUIRKS AND BUGS THE CURRENT VERSION HAS, WE PROMISE TO KEEP THOSE IN FUTURE VERSIONS", but also may provide for convenient or efficiency via 'tricky' coding. Somewhere in between is (my) ideal. Imagine if SQL said "Inserting multiple records use a select on the table you are inserting into is undefined." Programmers everywhere would nod their heads wisely and say "Good call". And some implementations would allow it, some wouldn't, and some people would accidentally rely on it, and others would be pissed to not be able to. Before it seems like I'm taking a strong stand for modification during iteration: In my opinion, the only problem in this situation is simply that the documentation for Hash#each provides no information. "We've gotta be able to get some kind of reading on that shield, up or down!" Ideally, in my mind, we should document: a) [Implementation] How each iterating method happens to behave currently with respect to additions, modifications, and deletions during traversal, and b) [Design] What is intended to be true about the implementation for (foreseeable) future versions, and may be relied upon. If the documentation for Hash#each said that inserting new entries during traversal might cause an infinite loop, I never would have even started this topic. And (possibly) the real-world bugs that happened to exist in Ramaze that caused it to hang when moving from 1.8 to 1.9 would never have been coded. I'll take this to ruby-core and see if I can gather details on Design for a variety of methods, and offer up a doc patch. If anyone here can provide any details about either Implementation or (for sure) Design, I'd be happy to hear it.