What's the point of a lambda expression?

After reading this article, I can't figure out why lambda expressions are ever used. To be fair, I don't think I have a proper understanding of what delegates and expression tree types are, but I don't understand why anyone would use a lambda expression instead of a declared function. Can someone enlighten me?


Solution 1:

First: brevity and locality:

Which would you rather write, read and maintain? This:

    var addresses = customers.Select(customer=>customer.Address);

or:

static private Address GetAddress(Customer customer)
{
     return customer.Address;
}

... a thousand lines later ...

    var addresses = customers.Select(GetAddress);

What's the point of cluttering up your program with hundreds or thousands of four-line functions when you could just put the code you need where you need it as a short expression?

Second: lambdas close over local scopes

Which would you rather read, write and maintain, this:

var currentCity = GetCurrentCity();
var addresses = customers.Where(c=>c.City == currentCity).Select(c=>c.Address);

or:

static private Address GetAddress(Customer customer)
{
     return customer.Address;
}

private class CityGetter
{
    public string currentCity;
    public bool DoesCityMatch(Customer customer)
    {
        return customer.City == this.currentCity;
    }
}

....

var currentCityGetter = new CityGetter();
currentCityGetter.currentCity = GetCurrentCity();
var addresses = customers.Where(currentCityGetter.DoesCityMatch).Select(GetAddress);

All that vexing code is written for you when you use a lambda.

Third: Query comprehensions are rewritten to lambdas for you

When you write:

var addresses = from customer in customers
                where customer.City == currentCity 
                select customer.Address;

it is transformed into the lambda syntax for you. Many people find this syntax pleasant to read, but we need the lambda syntax in order to actually make it work.

Fourth: lambdas are optionally type-inferred

Notice that we don't have to give the type of "customer" in the query comprehension above, or in the lambda versions, but we do have to give the type of the formal parameter when declaring it as a static method. The compiler is smart about inferring the type of a lambda parameter from context. This makes your code less redundant and more clear.

Fifth: Lambdas can become expression trees

Suppose you want to ask a web server "send me the addresses of the customers that live in the current city." Do you want to (1) pull down a million customers from the web site and do the filtering on your client machine, or (2) send the web site an object that tells it "the query contains a filter on the current city and then a selection of the address"? Let the server do the work and send you only the result that match.

Expression trees allow the compiler to turn the lambda into code that can be transformed into another query format at runtime and sent to a server for processing. Little helper methods that run on the client do not.

Solution 2:

The primary reason you'd use a lambda over a declared function is when you need to use a piece of local information in the delegate expression. For example

void Method(IEnumerable<Student> students, int age) {
  var filtered = students.Where(s => s.Age == age);
  ...
}

Lambdas allow for the easy capture of local state to be used within the delegate expression. To do this manually requires a lot of work because you need to declare both a function and a containing type to hold the state. For example here's the above without a lambda

void Method(IEnumerable<Student> students, int age) {
  var c = new Closure() { Age = age };
  var filtered = students.Where(c.WhereDelegate);
  ...
}

class Closure {
  public int age;
  bool WhereDelegate(Student s) {
    return s.Age == age;
  }
}

Typing this out is tedious and error prone. Lambda expressions automate this process.

Solution 3:

Let's leave expression trees out of the equation for the moment and pretend that lambdas are just a shorter way to write delegates.

This is still a big win in the realm of statically typed languages like C# because such languages require lots of code to be written in order to achieve relatively simple goals. Do you need to compare sort an array of strings by string length? You need to write a method for that. And you need to write a class to put the method into. And then good practice dictates that this class should be in its own source file. In any but the smallest project, all of this adds up. When we 're talking about small stuff, most people want a less verbose path to the goal and lambdas are about as terse as it can get.

Furthermore, lambdas can easily create closures (capture variables from the current scope and extend their lifetime). This isn't magic (the compiler does it by creating a hidden class and performing some other transformations that you can do yourself), but it's so much more convenient than the manual alternative.

And then there are expression trees: a way for you to write code and have the compiler transform this code into a data structure that can be parsed, modified and even compiled at runtime. This is an extremely powerful feature that opens the door to impressive functionality (which I definitely consider LINQ to be). And you get it "for free".

Solution 4:

http://msdn.microsoft.com/en-us/magazine/cc163362.aspx

Great article on what lambdas are, and why you can/should use them.

Essentially, the lambda expression provides a shorthand for the compiler to emit methods and assign them to delegates; this is all done for you. The benefit you get with a lambda expression that you don't get from a delegate/function combination is that the compiler performs automatic type inference on the lambda arguments

Solution 5:

They are heavily used with LINQ, actually LINQ would be pretty bad without it. You can do stuff like:

Database.Table.Where(t => t.Field == "Hello");