Skip to content

A Functional ForEach

When looping through an array, I am a big fan of using For Each as I find it more readable than using a For loop with a counter and looking up the item in the array with the counter.

Such a loop might look like this:

Var xdcs() As String = Array("Orlando", "Austin", "Houston", _
"Las Vegas", "Denver", "Miami")

For Each city As String in xdcs
  Display(city)
Next

The Xojo Developer Conference, aka XDC, is the biggest Xojo event of the year. We’re looking forward to XDC London in October 2021.

Here is the code for the Display method:

Public Sub Display(it As String)
  ListBox1.AddRow(it)
End Sub

But what if you wanted to simplify things even further? Say you want to write code like this:

xdcs.ForEach(Display)

Is that even possible in Xojo? Yes, it mostly is, with a couple things called Extension Methods and Delegates.

To set this up, add a Module to your project and add a Delegate to the module. A Delegate is a type that is a method declaration. Here are its specifics:

  • Delegate Name: ForEachString
  • Parameters: it As String
  • Scope: Global

Any actual method that matches this delegate signature is said to satisfy the delegate. If you look at the Display method above, you’ll see that it matches this delegate’s signature. So the Display method could be passed into a parameter of this delegate type.

In the same module, add a method. This will be an extension method on a string array. An extension method is a method that is called using dot notation on a specific data type (or class), even though it is not specifically part of the data type. This method also takes the delegate defined above as a parameter. Here are the method specifics:

  • Method Name: ForEach
  • Parameters: Extends stringArray() As String, action As ForEachString
  • Scope: Global

Its code still uses For Each and calls the delegate like this:

For Each s As String In stringArray
  action.Invoke(s)
Next

Note: The above method and delegate are designed to work with String arrays. To work with other array types you’d need to add equivalent delegates and ForEach method overloads.

With these pieces now in place, this code (which is almost exactly what we wanted above — AddressOf is used to pass a reference of the Display method to the delegate) now works:

Var xdcs() As String = Array("Orlando", "Austin", "Houston", _
"Las Vegas", "Denver", "Miami")

xdcs.ForEach(AddressOf Display)

The above code is slightly shorter since it doesn’t need to declare the variable, but was this really worth all this this effort just for that? Well, perhaps not, but I think it’s cool and sometimes it’s fun to do stuff just because you can! Plus, it makes for a good excuse to learn about some more advanced Xojo features. Either way, I hope you found this interesting.