Lambdas and Closures and Currying. Oh my! (Part 2)

View the whole series:

Functional Programming Series

So, in the last part of this series we discussed functional programming languages in general and we discussed closures, and how they were simply methods that are bound to external variables. In C# 2.0 this was only implemented with anonymous methods. In C# 3.0 we are introduced to the lambda. A lambda is for the most part syntactic sugar for anonymous methods. Lets look at an example of a lambda.

Sidenote:

There are very subtle differences, and you can read Eric Lippert’s post on it if you want to know more.

    //Rob Conery should like the variable 
    Func<int, int> elLambda = (int x) => x * 2;

This lambda can be called like this

    elLambda(5);

And it would return 10.

But wait, that statement works, but the syntax doesn’t look *that* much better than an anonymous method, and you are correct. It is a good thing that C# 3.0 has much improved type inference. Because of this, we can remove most of the cruft from this statement. We can the rewrite it like this…

    var elLambda = x => x * 2;

Sidenote:

The "var" keyword was added in C# 3.0 and while it may look like C# 3.0 has introduced dynamic typing, this is not the case. The var just allows the type to be inferred. In this case, we can tell that elLambda is a Func<int> and therefore it will become that type and compile just as if you had written it explicity like that. For example, if we had this…

    var i = 1;
    i = "";

This would work in a dynamically typed language, the variable’s implicit type would simply change. In C# 3.0 this would result in a compile time error of "Cannot implicitly convert type string to int"

The only problem is that this no longer compiles. We get an error that says "Cannot assign lambda expression to an implicitly-typed local variable". Hmm, maybe we need to add a type to x, since currently there is not enough information for the type to be inferred. So we change the call to this..

    var elLambda = (int x) => x * 2;

Close, but no cigar. Apparently we still cannot assign to this implicit local variable, why is this? Well, it has to do with expression trees. (Which I will hopefully touch on later on down the road) Basically, the compiler does not know if we want this lambda expression to be compiled into a delegate, or we want it to be turned into an expression tree that can be passed to a method. So, we could do a few things. We could remove the "var" and replace it with "Func<int,int>" or we could cast the whole lambda to a Func<int,int>. In both of these cases we could drop the "int" off of the lambda parameter. These options would end up looking like this…

    Func<int,int> elLambda = x => x * 2;
    var elLambda = (Func<int,int>)(x => x * 2);

Neither of these are particularly elegant solutions, and won’t help you at all if you are using anonymous types. It is a good thing that we do have another option. We can create a method that will return our lambda as a particular type.

  public static Func<TArg, TResult> GetFunc<TArg, TResult>
    (Func<TArg, TResult> lambda)
  {
    return lambda;
  }

This also may look a bit convoluted to you, but it is generic for any single argument method. It can be changed for two, three, four, etc… argument methods. Essentially you are passing the lambda into the generic method "GetFunc". Because the type of the parameter is is "Func<TArg, TResult>" the compiler knows that the expression needs to be a delegate, and therefore compiles it normally and doesn’t try to turn it into an expression tree. Then we just return our lambda, and the C# compiler no longer has any problem assigning to the implicit local variable. We can then call it like this…

    var elLambda = GetFunc((int x) => x * 2);

Keep in mind that we still need the "int" to be there because the compiler still doesn’t know enough information about x to infer what type we are trying to use. The good news is that most of the time when you are using lambdas you are not going to have to worry about most of this. The short syntax of a lambda makes it easy to pass as a parameter, and most of the time you will be doing something like this…

  var numberList = new List<int>() { 5, 4, 3, 9, 15, 6, 3, 22, 55 };
  List<int> greaterThanFiveList = numberList.FindAll(n => n > 5);
 
  foreach (int num in greaterThanFiveList)
  {
    System.Console.WriteLine(num);
  }

So, as you can see we are declaring a list of a bunch of numbers (using the C# 3.0 collection initializers!) and then we are passing our lambda expression into the FindAll method on the list. This method has existed since C# 2.0 and it takes a parameter of type Predicate. Predicate is just a delegate that is declared like this…

    delegate bool Predicate<T>(T obj);

So, because we have declared the type of our List as "int", the compiler has made the "FindAll" method take a Predicate<int> and so the C# compiler can infer that n is supposed to be an int.

So, now that you know what a lambda is, let me add one or two things onto the end here. First of all a lambda can also represent a method block rather than just a single statement. This allows us to do simple expressions and then have a return statement.

  var elLambda = GetFunc((int x) => { if (x > 5) { return x * 2; }
    else { return x * 3; } });

You probably don’t want to get much crazier than that, it quickly becomes difficult to read. You can break it down into multiple lines, but I think that readability still suffers when it gets more complicated than this. It would be better to assign the lambda to a variable.

So, in conclusion, you have seen a thorough explanation of the C# language syntax for lambdas. In the next post we are going to talk a little bit more about methods that take lambdas and hopefully get into some more examples of how you would want to use them.

Be Sociable, Share!

2 comments

  1. I recently bloged about a similar topic.
    One correction I want to make is that you say that you can not do:
    var elLambda = x => x * 2;
    because the compiler doesn’t know whether to make expression tree or function but that is not correct. It vb you can do:
    dim f = function (x) x *2
    and it works fine.

    The reason it doesnt work in C# is because the C# compiler sees the query and doesnt know what type x is or the return value of the function. VB doesn’t care becuase it just assume they are object and since in vb functions on objects are late bound there is no compile error.

    I describe this http://blogs.msdn.com/matt/archive/2007/12/06/lambda-expressions-are-more-fun-in-visual-basic-net.aspx

    and I am currently writing another post going into detail about how VB’s late binding works in this case.

    Cheers’
    Matthew Manela

  2. Well, I was merely trying to point out that there is an ambiguity in determining the return type of the lambda. For example…

    Func<int,int> lammy = x => x * 2;
    versus
    Expression<Func<int, int>> lammy2 = x => x * 2;

    Even if we knew the types there would still be an ambiguity in which one we are creating. But yes, you are correct in that without this ambiguity it would still fail in C# because the C# compiler will want to know the type of "x".

    In VB.net if you are programming with "Option Strict On" (which most people consider best practice) you will be bound by the same rules and the type of x will not be inferred. Another thing that you will have to deal with (if I am not mistaken) is that this lambda will also have to deal with boxing an unboxing of any primitive types used in the lambda, since all it is really doing is just inferring the type as "Object". This will result in a nice performance hit if you are using this lambda a large number of times.

    Thanks for the thought provoking comment though, I am definitely going to have to subscribe to your blog, there isn’t very many bloggers interested in these sorts of things. :-)

Leave a comment