Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

One aspect of Groovy ( and Ruby, Python , etc ) I really like is the combination of closures and support for them in the Groovy DK .

As an example, consider iterating through every line in a text file :

Groovy

Code Block
file = new File("c:/dynamic.ini");
file.eachLine{
    println(it)
}

Very elegant and easy on the old eyes.

Java

Code Block
BufferedReader  input = null;
try {
      input = new BufferedReader (new FileReader("c:/dynamic.ini")); 
      String line;
      while ((line = input.readLine()) != null) {
	System.out.println(line);
      }
} finally {
   if(input != null){
       input.close();
   }
}

Oh dear.

Java with some help

Code Block
Iteration.eachLine("c:/dynamic.ini", new LineHandler() {
	public void handleLine(String line) {
		System.out.println(line);
	}
});

and the supporting code :

Code Block
 
public static void eachLine(String path, LineHandler handler) throws IOException {
	FileReader file = null;
	try {
		file = new FileReader(path); // Open the file.
		BufferedReader input = new BufferedReader(file);
		String line;
		while ((line = input.readLine()) != null) {
			handler.handleLine(line);
		}
	} finally {
		if (file != null) {
			file.close();
		}
	}
}

C#

Apologies for my C#, I have not been writing it for very long...

Code Block
string line;
using (StreamReader reader = File.OpenText(@"c:\dynamic.ini")) {
    while((line = reader.ReadLine()) != null){
        Console.WriteLine(line);
    } 
}

No need to escape path string is nice

C# 2.0 with some help

With C# 2.0 and the 2.0 .NET framework the addition of anonymous delegates we can produce a very concise and readable solution

Code Block

Iterators.EachLine(@"c:\dynamic.ini", delegate(string it) {
   Console.WriteLine(it);
});

similar in elegance to the Groovy one.

This depends on the following utility class

Code Block
public static class Iterators {

     public delegate void Closure<T>(T it);

     public static void EachLine(string path, Closure<string> closure) {
            string line = null;
            using (StreamReader reader = File.OpenText(path)) {
                line = reader.ReadLine();
                while (line != null) {
                    closure(line);
                    line = reader.ReadLine();
                }
            }
        }
 }

Groovinating C#

You will notice that I have started implementing the Groovy DK set of collection iterators (each, findAll, find , etc ) for C# 2.0.

I do wish Microsoft and Sun would have built this kind of simplicity in....

There are 2 possible approaches to the Collections :

  1. Subclass and add the grooviness
  2. Add the grooviness as a set statci methods you plass the collection to

Here is some perlimenary code and tests of both types.
This subclasses List<T> and adds the groovination, and offers the same support ina static class

C# 2.0 Code

Code Block
#region Using directives

using System;
using System.Collections.Generic;
using System.IO;

#endregion

namespace Groovinator {

    #region Delegatros
    public class Delegatros {
        public delegate void Closure<T>(T it);
        public delegate T Functor<T>(T it);
        public delegate bool Predicate<T>(T it);
    }

    #endregion
    #region Collection Iterators

    public class List<T> : System.Collections.Generic.List<T> {
        public void Each(Delegatros.Closure<T> closure) {
            foreach (T it in this) {
                closure(it);
            }
        }
        
        public List<T> FindAll(Delegatros.Predicate<T> predicate) {
            //this is a bit poor 
            List<T> result = new List<T>();
            foreach (T it in this) {
                if (predicate(it)) {
                    result.Add(it);
                }
            }
            return result;
        }

        public T Find(Delegatros.Predicate<T> predicate) {
            foreach (T it in this) {
                if (predicate(it)) {
                    return it;
                }
            }
            return default(T);
        }

        public void Map(Delegatros.Functor<T> functor) {
            List<T> result = new List<T>();
            for(int i = 0;i< this.Count;++i){
                this[i] = functor(this[i]);
            }
        }
    }


    public static class Iterators {
        
        // Collections
        public static void Each<T>(IEnumerable<T> enumerable, Delegatros.Closure<T> closure) {
            foreach (T it in enumerable) {
                closure(it);
            }
        }

        public static List<T> FindAll<T>(IEnumerable<T> enumerable, Delegatros.Predicate<T> predicate) {
            //this is a bit poor 
            List<T> result = new List<T>();
            foreach (T it in enumerable) {
                if (predicate(it)) {
                    result.Add(it);
                }
            }
            return result;
        }

        public static T Find<T>(IEnumerable<T> enumerable, Delegatros.Predicate<T> predicate) {
            foreach (T it in enumerable) {
                if (predicate(it)) {
                    return it;
                }
            }
            return default(T);
        }

        public static List<T> Map<T>(IEnumerable<T> enumerable, Delegatros.Functor<T> functor) {
            List<T> result = new List<T>();
            foreach (T it in enumerable) {
                result.Add(functor(it));
            }
            
            return result;
        }


    }

    #endregion
    #region File Iterators
    public static class IOIterators{
        // File related iterators
        public static void EachLine(string path, Delegatros.Closure<string> closure) {
            string line = null;
            using (StreamReader reader = File.OpenText(path)) {
                line = reader.ReadLine();
                while (line != null) {
                    closure(line);
                    line = reader.ReadLine();
                }
            }
        }
    }
    #endregion
}

Some Usage Examples

Code Block
// open, print all lines of a text file , close
IOIterators.EachLine(@"c:\dynamic.ini", delegate(string it) {
    Console.WriteLine(it);
});

List<string> list = new List<string>();

// populate list

// print a list of string
list.Each(delegate(string it) {
    Console.WriteLine(it);
});


System.Collections.Generic.IEnumerable<string> res;

// find all items matching the predicate item.Contaons("8")
res = list.FindAll(delegate(string it) {
    return it.Contains("8");
});

// find the first item where Item.Equals("10")
string ten = list.Find(delegate(string it) {
    return it.Equals("10");
});


List<int> nums = new List<int>();
for (int j = 1; j < 11; ++j) {
    nums.Add(j);
}

// apply a functor ( multiply by 2 ) to a list of ints
nums.Map(delegate(int num) {
        return num * 2;
});