C# 3.0: Lambda expressions. I don't like it that much

This is the my third post on the series of post I am making on C#3.0 after it got declared on PDC. See the previous two here and here.

It's not that I do not like lambda expression, I just don't like that its being supported in C#. Lets first see what its like and then I'll clarify on why I do not like it. If you are just interested on why I do not like it, go to the end of this post.

What is Lambda Expression

In C#2.0 anonymous methods were introduced ( :(  I'm already using past tense on a product that is still not formally released). It required a little cumbersome syntax to create in-line function block like the ones supported by many functional languages. Lambda expressions in C# along with type inference give a cleaner (????) way of declaring and using anonymous methods.

Lambda expressions are based on lambda calculus. Many functional languages like Lisp use lambda notations to define functions. Typical lambda expressions in C# can contain both expressions and or statement blocks.

 x => 2 * x // this is a expression
y => {return 2*x; } // this is a statement block

                    // and not supported in the PDC bits.

Here the => is the lambda operator.

The following delegate and lambda expression are equivalent and the lambda expression here is automatically converted into a corresponding delegate.

 delegate

T Func<T>(T t);
Func<int> funcDel = delegate(int x)
{
return x + x;
};

Func<int> lambda = x => x + x;

Console.WriteLine(funcDel(5));
Console.WriteLine(lambda(5));

For the lambda expression the type can be explicitly specified or it can be implicit and the complier can figure it out. So the above expression could be written as

 Func

<int> lambda = (int x) => x + x;

Lambda with Extension methods

Writing predicate functions for the extension methods becomes real easy with  lambda expressions. The System.Query namespace comes with nifty extension methods which use predicates. The following using the Where extension method prints out all the integers in the array which is less than 3

 int

[] a = new int[] { 1, 2, 2, 3, 3, 5, 6 };
var lessThan3 = a.Where(x => x < 3);
foreach(var val in lessThan3)
Console.WriteLine(val);

Type Inference and Lambda Expression

When a generic method is called without explicitly giving its type then the compiler can infer the type. In the following case both calls to GenericFunc is equivalent and will print System.Int32

 static void GenericFunc<T>(T t)
{
    Console.WriteLine(t.GetType().ToString());
}
GenericFunc(5); // Type is inferred
GenericFunc<int>(5);

Just like any other expression when a lambda expression is passed as a parameter to a generic function it is used to infer the type. Lets take the following example which is a modified version of the one used in the C# 3.0 spec

 delegate R Func<A, R>(A a);

// the generic function
static Z FuncInfer<X, Y, Z>(X value, Func<X, Y> f1, Func<Y, Z> f2)
{
    return f2(f1(value));
}
var size = FuncInfer(@"c:\vcvars32.bat", s => new FileInfo(s), t => t.Length);

Lets see how the type inference happens here.

  • Since the first parameter is a string, compiler looks at it and infers X to be a string.
  • For the first lambda expression the input type is X so sbecomes a string. Since it returns FileInfo the return type of it and hence Y becomes FileInfo.
  • For the second lambda expression Y is the input type and so t is FileInfo.
  • The second lambda returns FileInfo.Length so Z becomes long and hence size is a long and contains the size of the file passed as the first argument.

Why I don't like lambda expression in C#

C# has originally developed from C++ /Java and is (was :^) ) a strongly typed object-oriented language. The new features being introduced like closure, continuation (yes, yes very limited continuation) in C#2.0 and now type inference, lambda expressions are de-generating the language. Even though there are people go gaga about continuation and lexical closures these are fundamentally functional language features and should be left to that. Introduction of bits and pieces of functional language features are not going to add value to C# and at the same time the surface area of C# is growing beyond what most developer can grasp.

Every language has a domain of application and an audience. Most people who work in C# developing web-services and web-based applications today are not necessary computer science grads. For them these concepts are a huge variation from the way C# used to behave. Functional programming is for the academia and not from the industry and should be left as such.

If I am asked, whether I'll use these language features, my answer will be maybe, and that is because the code written by me will be reviewed and maintained by people in MS who are fairly conversant with these. However, I think these features add burden to the learning curve of people who are not super interested in C# and should be avoided in favor of easier language constructs’ that might take couple of lines of code more, but would be more readable and maintainable.

These are just my opinions and I'm sure the designers of C# had given a lot of thought before adding them, but I strongly feel that these features are just adding more surface area to the language and will mostly go unused by the masses.