[Gambas-user] modifying an enumerated set during the loop

B Bruen bbruen at ...2308...
Wed Jun 25 02:30:03 CEST 2014


I realise that modifying the enumerated set during a For Each loop is fraught with danger but I do have a situation where this is "necessary". The following is a very simplified mock up of an anomaly in gambas that I am seeing.  The real situation is complex, I'll explain it later in this post.

The following code shows several variants of changing the enumerated set during the loop.  (I could have also attached a source archive, but its probably quicker to just paste this in a new project main module.) The simulation is simply a "rocket launch count-down" .

Public Sub Main()

  Dim aTest As String[]
  Dim sItem As String
  
  ' Run 1: Simple enumeration (obviously works)
  aTest = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
  aTest.Reverse
  For Each sItem In aTest
    Print sItem
  Next
  Print "Blast off"
  
  ' Run 2: Nullify the whole array during the enumeration (continues as if enumeration is working on a copy)
  aTest = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
  Debug aTest
  aTest.Reverse
  Debug aTest ' prove that this is not duping the`array
  For Each sItem In aTest
    Debug aTest
    Print sItem
    If sitem = "8" Then aTest = Null ' but the enumeration continues???
  Next
  Print "Blast off"
  Print aTest = Null
  
  ' Delete (all) elements within the enumeration
  aTest = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
  aTest.Reverse
  For Each sItem In aTest
    Print sItem
    If sitem = "8" Then 
      aTest.Delete(0, aTest.Count) ' leaves a non-null but empty array, the loop exits once this has been executed
    Endif
  Next
  Print "Blast off"

End

Run 1 is just a simple enumeration, no changes are made to the set during the loop (sanity check !).
In Run 2, when the count gets to 8 we nullify the entire array. However, the enumeration loop still continues and includes all the elements from the original array???
In Run 3, when the count gets to 8 we delete the entire array. Now the enumeration stops at that point. This is what I would expect in Run 2???

In our real situation, we receive a bunch of xml "packets" (a packet being a complete xml document) that are queued for processing in such an array. Quite often, the list of packets to  be processed includes duplicate, or earlier, versions of some information relevant to a specific entity identified within the packet. So once we have processed the latest version, hence the array reversal, all packets containing earlier information regarding that entity are irrelevant.

In the real code we don't actually delete or nullify the queue array, but use a separate routine to remove the elements in the array that are no longer relevant, sometimes this will empty the reversed array entirely (or at least the rest of it). Now, as the Run 3 example works as I expect, i.e. the loop is "truncated", generally everything is fine. But, there are uncommon, but not infrequent, situations where the entire array can be nullified, this is what scares me as the code that handles this entire mess is spread out over multiple tasks and such like.

So, shouldn't the Run 2 loop truncate like Run 3?

regards
Bruce 

-- 
B Bruen <bbruen at ...2308...>




More information about the User mailing list