Joel on Software talks about the Swedish Chef and the advantages of anonymous functions and functional style programming with an example of map and reduce in Javascript.
He notes how terrible this is to implement in C with function pointers, or even worse in Java with functors. Thankfully, C# 2.0, with anonymous delegates and generics, offers a clean, type-safe way to do this, which doesn't require much more code than his javascript version. The only real additions are the declarations of the delegates used, and of course some necessary type specifications, because C# is still a strongly typed language.
So what does this code look like? The answer can be found below, with some more discussion on this Channel9 post made by me.
public delegate T MapDelegate<T>(T input); public delegate TAggregate ReduceDelegate<TAggregate, TInput>(TAggregate aggregate, TInput input); public static void Map<T>(IList<T> list, MapDelegate<T> function) { for( int x = 0; x < list.Count; ++x ) list[x] = function(list[x]); } public static TAggregate Reduce<TAggregate, TInput>(IEnumerable<TInput> list, TAggregate initial, ReduceDelegate<TAggregate, TInput> function) { TAggregate aggregate = initial; foreach( TInput item in list ) aggregate = function(aggregate, item); return aggregate; } public static void Foo() { List<int> list = new List<int>(new int[] { 1, 2, 3 }); // Multiply each element by 2. Map(list, delegate(int x) { return x * 2; }); // Sum values: result with be 12 int sum = Reduce(list, 0, delegate(int aggregate, int input) { return aggregate + input; }); // Concatenate values using a StringBuilder, result will be "246" string concat = Reduce(list, new StringBuilder(), delegate(StringBuilder aggregate, int input) { return aggregate.Append(input.ToString()); }).ToString(); }
EDIT 2006-08-04: Added code.
2007-03-29 12:46 UTC
Very nice use of style to color your code! I see you made classes for keywords, types, comments.
2008-06-23 17:05 UTC
Yes, it does.
Code in the D programming language:
http://codepad.org/RocdniAs
import std.string;
void Map(T)(T[] list, T delegate(T) func)
{
for( int x = 0; x < list.length; ++x )
list[x] = func(list[x]);
}
TAggregate Reduce(TAggregate, TInput)(TInput[] list, TAggregate initial, TAggregate delegate(TAggregate, TInput) func)
{
TAggregate aggregate = initial;
foreach( item; list )
aggregate = func(aggregate, item);
return aggregate;
}
void Foo()
{
auto list = [ 1, 2, 3 ];
// Multiply each element by 2.
Map(list, delegate(int x) { return x * 2; });
// Sum values: result with be 12
int sum = Reduce(list, 0, delegate(int aggregate, int input) { return aggregate + input; });
// Concatenate values using a StringBuilder, result will be "246"
string concat = Reduce(list, cast(string) "", delegate(string aggregate, int input) { return aggregate ~= toString(input); });
}
2009-07-15 20:08 UTC
Time to update this with lambda expressions :-).
2010-02-09 20:04 UTC
LOLOLOLOLOLOL....
Not even close to Lisp or Haskell, or even Ruby
LOL
Comments are closed for this post. Sorry.