dim arr() as integer = array( 1, 2, 3, 4 )
for each i as integer in arr
arr.Remove arr.IndexOf( i )
next
My understanding of For Each is that it guarantees that each element of an array will be put through the loop, so I’d expect arr to be empty when this loop is done. Instead, it acts just as if I had iterated over it using for i = 0 to arr.Ubound.
Should this be considered a bug? I’m not sure as the languages I arbitrarily tried this morning handled it differently. Applescript and PHP left me with an empty array while JavaScript worked like Xojo.
This is test code to demonstrate the issue only. In practice, I’d expect there to be an If in there somewhere. In fact, my production code is closing idle connections. I don’t know if some would have been missed or not, but that’s what lead me to test.
Yes, the substitute code you mentioned is how it works, but not really since order is not guaranteed.
PHP: not correct. PHP does not have indexed arrays as we know them from C, Xojo, etc. Every array in PHP a dictionary in Xojo terminology. See Understanding PHP’s internal array implementation. You can test it yourself:
[code]<?php
$array = array(1, 2, 3, 4);
foreach ($array as $value) {
$index = array_search($value, $array);
if ($index == 2) {
unset($array[$index]);
}
}
I think the differrence is that languages which compile to hardware have arrays, because they address the memory directly. Index 3 means go to the array variable’s memory location and jump 3 memory cells further.
This doesn’t make sense IMO. For Each is treating an array as a dictionary. The order of how the loop iterates over the elements is not guaranteed. If you want to iterate an array from the last to the first, use a For i As Integer = arr.Ubound DownTo 0 loop.
The built-in For Each … Next is syntactic sugar for a For … Next loop, where one does not care about the order of the traversal, and one does no’t need to access the key within the loop.
Yep, or do some clever copy-on-write setup that increases the complexity of the array code. It seems more likely that this edge case was turned into an exception if anything were to happen.
The fact that the current implementation of For/Each is similar if not exactly the same as For/Next is just that, an implementation detail. Order of traversal is not guaranteed simply because the implementation is free to change as conditions require, not because the current implementation isn’t linear.
That said, there are ways of implementing For/Each that are affected by inserting/deleting elements during the loop, and other ways that are not. There should be some mention in the documentation that you may get unpredictable results if you insert or remove elements from the array in a For/Each loop. If you need to modify the array, use For/Next where you can control the order (and iterate in reverse).
Thanks for all the comments. An IteratorException is indeed what you get if you iterate over, say, a Xojo.Core.Dictionary, so I guess that makes sense for an array too. At the very least, the documentation should be updated to make it clear that you are not guaranteed access to each element if the array changes mid-loop.