xojo.core.dictionary - iterator exception

Hi,

I’ve been using new xojo.core framework a lot but ran into issues where the new frame does
not offer functionality or convenience the old framework has. For instance I use dictionary a lot and iterating
over a dict is a nice thing but not if you use the new dictionary for queuing/dynamic things. The problem? adding/removing
items from a dict will
cause an exception within the loop:

[code]using xojo.core
dim d as new Dictionary
d.value(“1”) = 1
d.value(“2”) = 2
d.value(“3”) = 3

for each item as xojo.Core.DictionaryEntry in d
d.Value(“4”) = 4
next[/code]

The old framework offered a way to get all keys or values as array:

[code]dim d as new Dictionary

dim k() as string = d.Keys
dim v() as Variant = d.Values

for each key as string in k
d.Value(“4”) = 4
next[/code]

but the new dictionary you need to to it manually.

[code]dim k() as Text
dim v() as auto

for each item as xojo.Core.DictionaryEntry in d
k.apppend item.key
v.append item.value
next

for each key as Text in k

next[/code]

So my questions is there is better to handle such dynamic loops with a dictionary or if the key() and values() function
will be added to the new framework? What the best efficient way ?

The reason you are getting an exception is that you are adding an element to the dictionary which renders the iterator invalid.

In the old framework code, pulling the keys actually does the iteration ahead of time.

The best practice is to not change the dictionary when iterating over said dictionary.

I know the reason for the exception. It’s pretty clear :slight_smile: and yes it does mean: do no alter the dict while iterating but it did answer my question.

If you find this to be a common pattern in your project, you could add a method that takes an iterator and returns an array of Auto. Then your code would look something like:

Function EagerlyEvaluateIterable(obj As Xojo.Core.Iterable) As Auto()
  Dim results() As Auto
  For item As Auto In obj
    results.Append(item)
  Next
  Return results
End Function
For Each entry As Xojo.Core.DictionaryEntry In EagerlyEvaluateIterable(d)
  // Stuff that can mutate the dictionary
Next

Excellent Joe, that’s my answer! Maybe you guys can update the xojo dev documentation as this is really a good advice.

Function EagerlyEvaluateIterable(obj As Xojo.Core.Iterable) As Auto() Dim results() As Auto For each item As Auto In obj results.Append(item) Next Return results End Function