Adding an object to a list while looping the list

Monkey Forums/Monkey Programming/Adding an object to a list while looping the list

Farflame(Posted 2012) [#1]
I'm not sure if I have another error, or if this is something I don't understand about the For Eachin loop so it'd be nice to know how this works.

I'm looping through a list of objects. Whilst inside the loop, I'm occasionally needing to add another object to the list. I'm not sure how that affects the current loop. Will it now just continue to the end, including the newly added object, or only as far as the object which was the final object when the loop started?


AdamRedwoods(Posted 2012) [#2]
specifically List<type> would be myList.AddLast(object) or myList.AddFirst(object) to add objects. You could also add objects using nodes. It updates instantly, so therefore you could loop to infinity.

BUT-- here's something interesting. a one-item list does not repeat infinitely using FOREACH, but a 2-item list does.

Local mylist:List<Int> = New List<Int>
Local q:Int=1
mylist.AddLast(q)
'mylist.AddLast(q) ''will run until q>100
		
For Local me:= Eachin mylist
		
	Print q
		
	mylist.AddLast(q)
	q +=1
		
	If q>100 Then Exit
Next
possible bug? possible feature? a REPEAT-UNTIL loop would be able to get around this anomaly.


muddy_shoes(Posted 2012) [#3]
It's a matter of where the enumerator "pointer" is when you do the add.

The list enumerator updates the pointer on entering the loop as you retrieve the next item. When there's only one item, that pointer is immediately set to the special "head" node. That means that adding to the list won't extend the loop because the addition is behind the enumerator. When you have more than one item, AddLast is adding after the enumerator's current item, so it's possible to keep laying track in front of the train, as it were.

I guess it's a bug of the "possibly unexpected side-effect" variety. You could argue that it's just a quirk of the implementation though.


Samah(Posted 2012) [#4]
Since Diddy's ArrayList uses an indexed array rather than node objects, it's impossible for the enumerator to keep track of where it's up to if the list is modified between calls to HasNext/NextObject. That's why I put a modification semaphore on it, and it raises an error if you try to use it after the list has been modified.

Slightly annoying, but it's the price you pay for using an indexed array. You can still remove items by manually holding the enumerator object and calling Remove() to remove an object from the ArrayList (the object from the most recent call to NextObject).