Continuing our exploration of design patterns in Ruby and C#, we’re going to dive into the Iterator pattern. Like most design patterns, if you google (or bing) for an example you will run into several different implementations because there are many ways to iterate a collection of objects. In it’s classic (well, classing in the .Net\Java sense) form, the pattern is made of:

  1. An interface defining the iterator. This typically involves two methods: HasNext() and MoveNext().
  2. An concrete iterator implementation
  3. An interface defining an enumerable collection. The only method really needed here would be GetIterator() which will return the iterator object.
  4. A concrete enumerable implementation.

The book Design Patterns in Ruby actually defines that type of implementation as an external iterator. This form gives you a type of hook into the collection that allows you to pull out an object one at a time and work with it externally, away from the insides of the collection. The other type of implementation that it describes is an internal iterator. This form involves a method that passes logic (think anonymous method in C# or code block in Ruby) into a method on the collection. The collection then internally iterates through it’s items and applies the logic on each item. This is a very common way of working with collections in Ruby and is slowly building adoption in C#. As we work through the examples below, we’ll take a look at both external and internal implementations.

The following examples will consist of a used car sales lot which will consist of a collection of vehicles.

C# Example – External Iterator From Scratch

First off, let’s create a basic Vehicle object.

  
public class Vehicle
{
    public string Name { get; set; }

    public Vehicle(string name)
    {
        Name = name;
    }
}

Our next step is to create an ISimpleIterator interface which we’re going to make generic so we aren’t tied to a specific type of object. It really only needs two methods, HasNext() which will let us know if we’ve reached the end of the collection, and MoveNext() which will return the item in the next position.

  
public interface ISimpleIterator<T>
{
    bool HasNext();
    T MoveNext();
}

And now we’ll create a concrete implementation of the iterator.

  
public class SimpleIterator<T> : ISimpleIterator<T>
{
    private int _position = 0;
    private T[] _items;

    public SimpleIterator(T[] items)
    {
        _items = items;
    }

    public bool HasNext()
    {
        return _position < _items.Length;
    }

    public T MoveNext()
    {
        var item = _items[_position];
        _position++;
        return item;
    }
}

Next, let’s create our ISimpleEnumerable interface. We’ll keep this one generic as well since there’s no reason to lock it into only Vehicle objects. Note that it only needs one method that will return a generic ISimpleIterator.

  
public interface ISimpleEnumerable<T>
{
    ISimpleIterator<T> GetIterator();
}

And our enumerable object will be a SalesLot entity. The GetIterator() method will return a strongly typed vehicle iterator.

   
public class SalesLot : ISimpleEnumerable<Vehicle>
{
    private Vehicle[] _vehicles = {
                                     new Vehicle("Toyota Camry"), 
                                     new Vehicle("Jeep Grand Cherokee"),
                                     new Vehicle("Honda CRV")
                                 };

    public ISimpleIterator<Vehicle> GetIterator()
    {
        return new SimpleIterator<Vehicle>(_vehicles);
    }
}

Let’s see what this code would actually look like if we tried to run it. All we have to do is grab the iterator and wrap it in a while loop.

   
var salesLot = new SalesLot();
var vehiclesIterator = salesLot.GetIterator();

while (vehiclesIterator.HasNext())
    Console.WriteLine(vehiclesIterator.MoveNext().Name);

Output:

Toyota Camry
Jeep Grand Cherokee
Honda CRV

C# Example – External Iterator Using Built-In IEnumerable Interface

Our design can be hugely simplified by using the IEnumerable interface from the base class library. In the below code sample, our SalesLot object no longer returns an ISimpleIterator, instead it’s passes back a IEnumerator which is also built in the .Net framework. The two GetEnumerator() methods are all that’s needed to fulfill the IEnumerable interface contract. And since all built-in collections implement this interface, we can easily pass that call to the inner list.

   
public class SalesLot : IEnumerable<Vehicle>
{
    private IEnumerable<Vehicle> _vehicles = new List<Vehicle> {
                                     new Vehicle("Toyota Camry"), 
                                     new Vehicle("Jeep Grand Cherokee"),
                                     new Vehicle("Honda CRV")
                                 };

    public IEnumerator<Vehicle> GetEnumerator()
    {
        return _vehicles.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

And using it is just as easy as our earlier example.

   
var salesLot = new SalesLot();
var enumerator = salesLot.GetEnumerator();

while (enumerator.MoveNext())
    Console.WriteLine(enumerator.Current.Name);

And any class that implements the IEnumerable interface is also able to be iterated over using the foreach construct.

   
var salesLot = new SalesLot();

foreach (var vehicle in salesLot)
    Console.WriteLine(vehicle.Name); 

C# Example – Adding an Internal Iterator to the SalesLot Class

The previous examples all used external iterators to navigate the collection of cars. But we could have easily used an internal iterator as well. To do this, we need to add a method to the SalesLot object that will allow us to pass in an anonymous method or lambda expression to apply to each vehicle in the collection.

   
public class SalesLot
{
    private IEnumerable<Vehicle> _vehicles = new List<Vehicle> {
                                     new Vehicle("Toyota Camry"), 
                                     new Vehicle("Jeep Grand Cherokee"),
                                     new Vehicle("Honda CRV")
                                 };

    public void ForEach(Action<Vehicle> action)
    {
        foreach (var vehicle in _vehicles)
            action(vehicle);
    }
}

And using it becomes just a couple lines of code.

   
var salesLot = new SalesLot();
salesLot.ForEach(vehicle => Console.WriteLine(vehicle.Name));

C# Example – Internal Iterator Using the Built-In ForEach List Extension Method

With the addition of Linq, we were given a ForEach extension method on generic lists. Using it is exactly the same as our hand-rolled example.

   
var salesLot = new List<Vehicle> {
                             new Vehicle("Toyota Camry"), 
                             new Vehicle("Jeep Grand Cherokee"),
                             new Vehicle("Honda CRV")
                         };

salesLot.ForEach(vehicle => Console.WriteLine(vehicle.Name));

Ruby Example – External Iterator From Scratch

To get started with our Ruby examples, we’ll create our Vehicle object.

  
class Vehicle
  attr_accessor :name

  def initialize(name)
    @name = name
  end
end

And since Ruby suports duck-typing, we don’t need to create an abstract class or interface to define our iterator. We just need to make sure it has the appropriate methods. Notice that our functions that return a value (such as has_next or move_next) do not need to include the “return” keyword. In Ruby the last line of a mehod is the return value.

  
class SimpleIterator
  def initialize(items)
    @items = items
    @position = 0
  end

  def has_next
    @position < @items.length
  end

  def move_next
    item = @items[@position]
    @position += 1
    item
  end
end

We are also free to go ahead with creating the SalesLot class without defining an Enumerable abstraction as long as we include a get_iterator method that returns a SimpleIterator.

  
class SalesLot
  def initialize
    @vehicles = [Vehicle.new("Toyota Camry"), Vehicle.new("Jeep Grand Cherokee"), Vehicle.new("Honda CRV")]
  end

  def get_iterator
    SimpleIterator.new(@vehicles)
  end
end

Actually using the class is very similiar to the C# example.

  
sales_lot = SalesLot.new
vehicle_iterator = sales_lot.get_iterator

while vehicle_iterator.has_next
  puts vehicle_iterator.move_next.name
end

Output:

Toyota Camry
Jeep Grand Cherokee
Honda CRV

Ruby Example – Creating an Internal Iterator Using the Enumerable Module

While external iterators have their place, Rubyists tend to favor using internal iterators when working with collections. We could easily tack on our own for_each method to the SalesLot object (as we did in the C# example) but instead let’s jump straight into some of the cool things we can leverage in the library. Ruby ships with a handy module called Enumerable that we can include on our SalesLot object which will give us a lot of functionality for free. To use it, we just need to include the Enumerator module and add an “each” method that accepts a code block.

  
class SalesLot
  include Enumerable

  def initialize
    @vehicles = [Vehicle.new("Toyota Camry"), Vehicle.new("Jeep Grand Cherokee"), Vehicle.new("Honda CRV")]
  end
  
  def each(&amp;amp;amp;amp;amp;block)
    @vehicles.each(&amp;amp;amp;amp;amp;block)
  end
end

To be able to take advantage of the features given to us from the Enumerable module, our Vehicle needs to add a method defining the “<=>” comparison operator. This method accepts another Vehicle record to compare to and will return -1, 0, or 1 depending on whether the receiver is less than, equal to, or greater than the vehicle being passed in as an argument. For those of you familiar with the IComparable interface in .Net, this works exactly the same way.

  
class Vehicle
  attr_accessor :name

  def initialize(name)
    @name = name
  end

  def <=>(other)
    @name <=> other.name
  end
end

And now we can iterate through our collection in just a couple of lines.

  
sales_lot = SalesLot.new
sales_lot.each {|vehicle| puts vehicle.name}

But that’s just the tip of the iceberg. We are given a lot of added functionality that allows us to search and sort vehicles in the sales lot.

  
sales_lot.include? "Ford Escape"
sales_lot.find_all {|vehicle| vehicle.name.length > 12}
sales_lot.sort

And this functionality is available when working with arrays which allows us to do a lot of work with our collections without having to write much code.

  
vehicles = [Vehicle.new("Toyota Camry"), Vehicle.new("Jeep Grand Cherokee"), Vehicle.new("Honda CRV")]
vehicles.each {|vehicle| puts vehicle.name}

While the iterator pattern may look complex in it’s natural form, both Ruby and C# give us a lot of capabilities out of the box. Neither need much (if any) customization to do advanced work with collections.

Next time, we’ll check out the Command pattern!

kick it on DotNetKicks.com