article source: https://github.com/dzzie/libs/tree/master/experiments/vb6_enumerate
so in python there is a shortcut
for index,value in enumerate(array):
this is shorthand for
Code:
for i = lbound(array) to ubound(array)
value = array(i)
...
I know we have for each but then you dont have the index which you might need to set array(i) sometimes
so I am wondering if we can do something similar and use it like a built in language feature.
features:
supports arrays and collections
simple usage: Do While enumerate(index, value, aryOrCollection, [collectionKey])
no pre setup required just call it, do not need to initialize the index,
single call to walk object, it sets index, value and collection key
not limited to variant type variables like for each (so you keep intellisense for class objects)
put this in a global class in your dll and it will be available like a new language feature
limitation: can not be used nested
Code:
PrivateSub Form_Load()
Dim i, v, sample, colkey
Dim c AsNew Collection
Dim l AsLong
List1.AddItem "Experiment using a user function like a built in language operator"
sample = Array("apple", "orange", "cat", "dog")
List1.AddItem "----- [ walk simple array ] -------"DoWhile enumerate(i, v, sample)
List1.AddItem " Index: " & i & " Value: " & v
c.Add v
sample(i) = i
Loop
List1.AddItem " Array Values now: " & Join(sample, ", ")
List1.AddItem "----- [ walk array with long var enumerator ] -------"'walk changed array, use long as enum variable (variant not required like for each)DoWhile enumerate(i, l, sample)
List1.AddItem " Index: " & i & " Value: " & l
Loop
List1.AddItem "----- [ enum collection of simple values ] -------"DoWhile enumerate(i, v, c)
List1.AddItem " Collection Index: " & i & " Value: " & v
LoopDim c1 As Class1 'class source: Public idSet c = New Collection
'build up a collection of class objects..For i = 0 To 3
Set c1 = New Class1
c1.id = i
c.Add c1, "key:" & i
Next'note the i we pass in here will be 4 and not initilized...'enumerate will detect the change in object and reset..'there can be a case if we were using same collection as last'enumerate call and i was not 0 we would be undefined behavior..'note we can use a Class1 variable as our enumerator and is not required to be variant'enumerator also supports enumerating the items collection key..not possible with for each..
List1.AddItem "----- [ walk obj collection with key and class obj var ] -------"
List1.AddItem "----- [ note i = " & i & " is unitilized ] -------"DoWhile enumerate(i, c1, c, colkey)
List1.AddItem " Objs Index: " & i & " Class1 id: " & c1.id & " ColKey: " & colkey
Loop
sample = Array("apple", "orange", "cat", "dog")
List1.AddItem "----- [ bug test 1 - incomplete loop exit + same obj enum ] -------"DoWhile enumerate(i, v, sample)
List1.AddItem " Index: " & i & " Value: " & v
If i = 1 ThenExitDoLoop
List1.AddItem "----- [ first enum call exited, enum again same i same obj ] -------"DoWhile enumerate(i, v, sample)
List1.AddItem " Index: " & i & " Value: " & v
Loop
List1.AddItem "----- [ ok maybe that is actually a feature..could be useful ] -------"' List1.AddItem "----- [ bug test 2 - nesting = endless loop :( ] -------"' 'and this will not work and do weird stuff..' Do While enumerate(i, v, sample)'' List1.AddItem " Array Index: " & i & " Value: " & v'' Do While enumerate(i, c1, c, colkey)' List1.AddItem " Objs Index: " & i & " Class1 id: " & c1.id & " ColKey: " & colkey' Loop'' LoopEndSub
bonus is that the value set as the enumerator does not have to be a variant as with for each
it can be a specific class type so intellisense is available for it
Code:
Dim c1 As Class1
DoWhile enumerate(i, c1, c)
List1.AddItem "Objs Index: " & i & " class 1 id: " & c1.id
Loop
trying to use a user function as if it was a built in language feature is tricky..you dont want extra
calls to initialize it or close it, you dont want to require class instances so it supports nesting..so you
can do pretty good as a language add on "feature" without overhead, but not bullet proof..