Categories: .Net, P# Posted by mheydt on 8/15/2007 3:47 PM | Comments (0)
Revisting the iterator pattern, revisited again
I was playing around with .NET 3.5 extension methods and lambda functions and it hit me that this will very closely get me to the syntax that I desire for iterating across collections.  If you remember from my earlier post, I was looking for a syntax like the following (which is kind of both C# and ruby-ish in style):

    int[] ia = new int[] { 5, 4, 3, 2, 1};
    iterate ia |x| do { Console.WriteLine(x); } where { x < 3; };



Well, what I was able to come up with is an extension method that can add an iterate method to a collection (basically, anything IEnumerable) that can take two lambda methods, one for selecting items, and the other for processing on each selected item.  For example, the following actual C# code is possible:

    int[] ia = new int[] { 5, 4, 3, 2, 1};
    ia.iterate(x => x < 3, x => Console.WriteLine(x));


The output of running this c# is:

2

1

One of the neat things about the lamba methods is that they can operate on variables declared in local method scope.  For example, take this example of building a list on the items between 2 and 4 and then printing out that list:

    int[] ia = new int[] { 5, 4, 3, 2, 1};
    List<int> result = new List<int>();
    ia.iterate(x => x >= 2 && x <= 4, x => result.Add(x));
    result.iterate(x => Console.WriteLine(x));


This prints out:

4

3

2

The code for this extension method is the following:

    public static class IterateExtension
    {
        public delegate void operationdelegate(object o);
        public delegate void operationdelegate<T>(T o);
        public delegate void selectiondelegate(object o);
        public delegate bool selectiondelegate<T>(T o);
        public static void iterate<T>(this IEnumerable<T> objects, operationdelegate<T> od)
        {
            foreach (T o in objects)
            {
                od(o);
            }
        }

        public static void iterate<T>(this IEnumerable<T> objects, selectiondelegate<T> sd, operationdelegate<T> od)
        {
            foreach (T o in objects)
            {
                if (sd(o))
                    od(o);
            }
        }

        public static void iterate(this IEnumerable objects, operationdelegate od)
        {
            foreach (object o in objects)
            {
                od(o);
            }
        }

        public static void iterate<T>(this IEnumerable objects, selectiondelegate<T> sd, operationdelegate<T> od)
        {
            foreach (T o in objects)
            {
                if ((sd(o)))
                    od(o);
            }
        }
    }

Categories: .Net, P# Posted by mheydt on 3/26/2006 4:41 PM | Comments (0)

The Iterate Pattern Revisited
Consider the previous pattern for iteration that I put forth:

        int[] ia = new int[] { 5, 4, 3, 2, 1};
        iterate ia |i| { Console.WriteLine(i); };

I was thinking the other night that it would be nice to provide a criteria for selection of elements for processing as it might be very likely that you may not want to apply code to every element.  My thoughts extend this to the following code snippet:

        int[] ia = new int[] { 5, 4, 3, 2, 1};
        iterate ia |i| do { Console.WriteLine(i); } where { i < 3; };

The do keyword precedes a code block (anonymous method / delegate) that is applied to all elements that match the criteria specified by the code block specified after the where keyword.

Functionally, I would think the runtime would iterate across each element, applying the where code block to each, and in the case of a true condition, then apply the do code to that element.  Additionally, perhaps it might be better to process the where code on all element first build a set of items to process, and then iterate across all of the result set with the do code block.