March 27, 2009

A C# implementation of the Ruby 'each' iterator

If you ever had a look at Ruby you probably saw things like the following in one of the many tutorials:


s1 = 0
(10...20).each { |x| s1 += x*x }
puts s1

s2 = 0
[3, 7, 9].each { |x| s2 += x*x }
puts s2

Really cool. First thing I loved straight away is the easy notation for ranges.
And then, of course, there's the each iterator which takes a block as parameter. Simply fantastic.

As a software developer who uses C# for most of his tasks at the moment, I was jealous. But then I thought: why just not do the same thing in C#?

Well, of course there is no fancy tripe-dot range notation is C#. But we can do it like this:

class Range
{
public static IEnumerable<int> FromTo(int from, int to)
{
int pos = from;
while (pos <= to)
{
yield return pos;
pos++;
}
}
}

Pretty easy to do with the help of the yield keyword.
OK, and what about each? You can implement that using a extension method:


static class IteratorExtensions
{

public static void Each<T>(this IEnumerable<T> enumerable, Action<T> action)
{
foreach (var item in enumerable)
{
action(item);
}
}
}

This defines a new method Each for IEnumerable<> types. It takes a parameter of type Action, which is a void method with one parameter of type T. Action is defined in the System namespace.
Now let's take Range.FromTo and Each together and we rewrite the above Ruby script in C#:



int s1 = 0;
Range.FromTo(10,20).Each(
delegate(int x)
{
s1 += x*x;
});

Hmm, that is nowhere near the simple notation of the Ruby script...
But wait. Instead of using an anonymous method we also can used a lambda construct. Let's try it on the second part of the Ruby script:



int s2 = 0;
new[] { 3, 7, 9 }.Each(x => s2 += x*x);


Much better! Actually it almost looks like the Ruby script.
Conclusion: Ruby is nice, but C# isn't too bad either... ;-)
blog comments powered by Disqus