Iterating over OrderedCollections

One of the things you want to do after having an OrderedCollection (aka List or Array) is to iterate over the elements. I’ll look at the languages I’m interested in: Smalltalk, Java, Objective-C, Ruby, Python, and C#.

First off, Smalltalk. I think they got it right, by having blocks / closures as being first-class elements of the language. You can re-use blocks and each block has its own scope. Here’s how to iterate in Smalltalk:

list do: [ |item| item doSomething]

Next up, Ruby. Ruby’s next because it comes closest to Smalltalk. It too has blocks. Here’s how to iterate in Ruby:

list.each { |item| item.doSomething }

Since we just did Ruby, let’s see how Python iterates:

for item in list:
  item.doSomething()

And why not… C# iteration:

foreach (ItemClass item in list) {
  item.DoSomething();
}

I’ve saved Java and Objective-C for the last because they are a bit more complicated than the rest, at least historically.

Java, pre-Java 1.5 / 5, many programmers used typed arrays and then used a for loop to iterate:

ItemClass[] list = new ItemClass[size];
// fill in the list
for (i = 0; i 
You could have also used either an Enumerator (if using the legacy Vector) or Iterator/ListIterator if using List. Java 1.5 gives you a much cleaner way to iterate:
for (ItemClass item : list) {
  item.doSomething();
}

Finally, Objective-C has something called NSEnumerator. Apple advises programmers to iterate this way:

NSEnumerator *enumerator = [list objectEnumerator];
id item;
while (item = [enumerator nextObject]) {
    [item doSomething];
}

But many of us aren't quite happy with this way of doing things. There's no type information, since id is any object. Making a method call, assigning to an object reference, and testing a boolean all in the while test is too much in one place. Jonathan 'Wolf' Rentzsch has a great page that dissects this and he offers a nice macro that boils down to:

nsenumerate(list, ItemClass, item) {
  [item doSomething];
}

I think that while this is much better, it just doesn't seem like it is in the right order. I modified Wolf's macro a bit and renamed it to "foreach":

foreach( ItemClass, item, list )  {
  [item doSomething];
}

Note that for these macros to work, you need to set the Project Setting "C Language Dialect" to either "C99" or "GNU99".

All of these seem to be good at limiting scope and lifetime of the item variables. There are two styles in use: the block iterator and the "enhanced for" iterator. I prefer the block iterator, but it doesn't seem to be available for most languages. The "enhanced for" is the next best and with the slight modification to Wolf's nsenumerate macro, they all look very similar.