digitalmars.D - Killing the array you're iterating over
- Nick Sabalausky (16/16) Feb 25 2005 How safe is it to do this?
- Nick Sabalausky (28/47) Feb 25 2005 I forgot to mention that in my particular case the line 'array=null;' is...
- Matthew (3/50) Feb 26 2005 I'll be very surprised if this is supported behaviour
- Walter (2/2) Feb 27 2005 In general, it is a very bad idea to try to modify a collection in the
- Matthew (6/9) Feb 28 2005 But is this non-standard behaviour?
- Unknown W. Brackets (10/17) Mar 15 2005 I agree; it is a common thing to do something such as this:
- Carlos Santander B. (35/39) Mar 01 2005 In my experience, foreach uses the original keys to iterate over:
- David Medlock (8/12) Mar 15 2005 Then why are these delegates using inout parameters?
How safe is it to do this? MyClass[] array; ... // Put stuff into array foreach(MyClass obj ; array) { if(/+ some condition that may occur in one of the iterations +/) { array = null; // Is this kosher? } ... // Do stuff, but nothing that touches array or obj } It works for me and simply has the effect of breaking out of the foreach loop at the end of the iteration. Is this behavior guaranteed? Or it is considered unsafe and likely to be either broken in certain circumstances or disallowed in the future?
Feb 25 2005
I forgot to mention that in my particular case the line 'array=null;' is happening from within a member function of obj. Specifically: class MyClass { void Foo() { Kill(); } } MyClass[] array; void Kill() { array = null; } void Run() { ... // Put stuff into array foreach(MyClass obj ; array) { if(/+ some condition that may occur in one of the iterations +/) { obj.Foo(); } ... // Do stuff, but nothing that touches array or obj } } Nick Sabalausky wrote:How safe is it to do this? MyClass[] array; ... // Put stuff into array foreach(MyClass obj ; array) { if(/+ some condition that may occur in one of the iterations +/) { array = null; // Is this kosher? } ... // Do stuff, but nothing that touches array or obj } It works for me and simply has the effect of breaking out of the foreach loop at the end of the iteration. Is this behavior guaranteed? Or it is considered unsafe and likely to be either broken in certain circumstances or disallowed in the future?
Feb 25 2005
I'll be very surprised if this is supported behaviour "Nick Sabalausky" <a a.a> wrote in message news:cvobgr$1q8u$1 digitaldaemon.com...I forgot to mention that in my particular case the line 'array=null;' is happening from within a member function of obj. Specifically: class MyClass { void Foo() { Kill(); } } MyClass[] array; void Kill() { array = null; } void Run() { ... // Put stuff into array foreach(MyClass obj ; array) { if(/+ some condition that may occur in one of the iterations +/) { obj.Foo(); } ... // Do stuff, but nothing that touches array or obj } } Nick Sabalausky wrote:How safe is it to do this? MyClass[] array; ... // Put stuff into array foreach(MyClass obj ; array) { if(/+ some condition that may occur in one of the iterations +/) { array = null; // Is this kosher? } ... // Do stuff, but nothing that touches array or obj } It works for me and simply has the effect of breaking out of the foreach loop at the end of the iteration. Is this behavior guaranteed? Or it is considered unsafe and likely to be either broken in certain circumstances or disallowed in the future?
Feb 26 2005
In general, it is a very bad idea to try to modify a collection in the middle of a foreach.
Feb 27 2005
But is this non-standard behaviour? I think it should be defined as such for all cases, even if there are some specific ones where it doesn't hold. Specifically, I think one should always be allowed to modify a collection (assuming it's modifiable) from within a foreach loop, but one the condition that the loop is terminated (by break / return / goto / exception) without any further iterations. "Walter" <newshound digitalmars.com> wrote in message news:cvtcmq$qkc$1 digitaldaemon.com...In general, it is a very bad idea to try to modify a collection in the middle of a foreach.
Feb 28 2005
I agree; it is a common thing to do something such as this: foreach (inout char c; str) if (c == 0) { // String contains invalid characters. str = null; break; } Kinda dumb example, but the point is there, I think. -[Unknown]But is this non-standard behaviour? I think it should be defined as such for all cases, even if there are some specific ones where it doesn't hold. Specifically, I think one should always be allowed to modify a collection (assuming it's modifiable) from within a foreach loop, but one the condition that the loop is terminated (by break / return / goto / exception) without any further iterations.
Mar 15 2005
Walter wrote:In general, it is a very bad idea to try to modify a collection in the middle of a foreach.In my experience, foreach uses the original keys to iterate over: char [] [int] collection; void foo (int key) { ... might add elements to collection ... } void bar () { collection[4]="carlos"; foreach(int key, char [] value; collection) foo(key); } This will only iterate once. Since I needed to iterate even with the new elements, I ended up doing something like this: void bar () { int [] keys; void [int] already; while(true) { keys=collection.keys; foreach(int key, char [] value; collection) if ( ! (key in already) ) { foo(key); already[key]; } if (keys==collection.keys) break; } } I think the algorithm can be improved, but the other solution I tried (keeping another collection with just the items not iterated yet, and adding and removing elements every time), didn't work. _______________________ Carlos Santander Bernal
Mar 01 2005
Walter wrote:In general, it is a very bad idea to try to modify a collection in the middle of a foreach.Then why are these delegates using inout parameters? IMO there should be a delegate with an IN parameter or an void opApply( int delegate( in Type OldValue, out Type NewValue ) type method. I have already used temp variables in my opApply methods to avoid accidentally doing just this sort of mutation. -David
Mar 15 2005