digitalmars.D.learn - Can remove AA elements during foreach?
- Nick Sabalausky (8/8) Feb 16 2013 Is this both legal and safe?:
- H. S. Teoh (17/28) Feb 16 2013 Both are unsafe, because opApply, byKey, byValue, rely on a pointer to
- Nick Sabalausky (4/31) Feb 16 2013 Yea, that's the fallback I was using. Not that it's critical, but I was
- Steven Schveighoffer (11/19) Feb 16 2013 Both are unsafe.
Is this both legal and safe?: foreach(key; assocArray) if(key != "foobar") assocArray.remove("foobar"); If not, then what about this?: foreach(key; assocArray.byKey()) if(key != "foobar") assocArray.remove("foobar");
Feb 16 2013
On Sat, Feb 16, 2013 at 06:59:59PM -0500, Nick Sabalausky wrote:Is this both legal and safe?: foreach(key; assocArray) if(key != "foobar") assocArray.remove("foobar"); If not, then what about this?: foreach(key; assocArray.byKey()) if(key != "foobar") assocArray.remove("foobar");Both are unsafe, because opApply, byKey, byValue, rely on a pointer to the current AA Slot and a pointer to the hash table to keep track of where they are. Modifying the AA while in the middle of doing this may cause strange effects, like the loop terminating prematurely, or traversing already-deleted items. Keep in mind that a rehash may occur during modification, so imagine what it will do if you're still iterating pointers to the original AA. For full fool-proofness, do this: auto keys = assocArray.keys; foreach (key; keys) doWhateverYouWantHere(key); T -- The fact that anyone still uses AOL shows that even the presence of options doesn't stop some people from picking the pessimal one. - Mike Ellis
Feb 16 2013
On Sat, 16 Feb 2013 16:20:30 -0800 "H. S. Teoh" <hsteoh quickfur.ath.cx> wrote:On Sat, Feb 16, 2013 at 06:59:59PM -0500, Nick Sabalausky wrote:Yea, that's the fallback I was using. Not that it's critical, but I was hoping there'd be a simple way to do it without a dynamic allocation.Is this both legal and safe?: foreach(key; assocArray) if(key != "foobar") assocArray.remove("foobar"); If not, then what about this?: foreach(key; assocArray.byKey()) if(key != "foobar") assocArray.remove("foobar");Both are unsafe, because opApply, byKey, byValue, rely on a pointer to the current AA Slot and a pointer to the hash table to keep track of where they are. Modifying the AA while in the middle of doing this may cause strange effects, like the loop terminating prematurely, or traversing already-deleted items. Keep in mind that a rehash may occur during modification, so imagine what it will do if you're still iterating pointers to the original AA. For full fool-proofness, do this: auto keys = assocArray.keys; foreach (key; keys) doWhateverYouWantHere(key);
Feb 16 2013
On Sat, 16 Feb 2013 18:59:59 -0500, Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> wrote:Is this both legal and safe?: foreach(key; assocArray) if(key != "foobar") assocArray.remove("foobar"); If not, then what about this?: foreach(key; assocArray.byKey()) if(key != "foobar") assocArray.remove("foobar");Both are unsafe. Note that with Dcollections, there is a special purge feature that allows safe removal while traversing: foreach(ref doPurge, key, value; &hashMap.purge) doPurge = (key != "foobar"); All dcollections' classes support this. There is a keys collection, but that does not support purge. I can actually add it pretty easily though... -Steve
Feb 16 2013