tags:

views:

260

answers:

9

I haven't really been able to get a firm grasp on creating and using lambda expressions. I know how to use them in linq statements, but I really don't understand what's going on behind the scenes. I also havent been able to find a complete tutorial on when to use them, how to define them, etc.

Second part...

They say that Javascript is a LAMBDA language, I know javascript fairly well, just wondering what types of concepts that apply to javascript lambdas and c# lambdas.

thrid part...

what is the difference between a functional language and an lambda language?

Any suggestions?

A: 

This http://msdn.microsoft.com/en-us/magazine/cc163362.aspx might be useful.

bjoshi
+5  A: 

I can't answer part three, but let me take a swing at 1 & 2 and maybe that will help you with 3.

Do you understand delegates? Because that's really all you're dealing with. The VS2010 documentation is very succinct on this.

At the root, a lambda is just an anonymous function passed into a delegate declaration. Or, put more simply method without the signature (return type, name, and parameters). The signature is implied by the usage.

Asking "when to use a lambda" is really asking the question "when should I use an anonymous function for a delegate" and really, I can't think of better scenarios than the ones LINQ uses them for as examples. AFAIK and understand, Javascript is a lambda language because you can pass methods around like variables and do so with anonymous methods, not just declared methods.

As far as reading a lambda, I don't like the "goes to" terminology used by some. I tend to read it like a normal method, which is to say:

"given some list of parameters, execute this code"

So, row=> row.State == "NY" means "Given row, return true when row's State is New York".

Maybe I'm oversimplifying, but I'm a simple guy.

Jim Leonardo
totally on board with your method of reading lambdas. That "goes to" stuff just sounds silly.
Dave
A: 

C# 3 in a Nutshell, as well as Jon Skeet's book tackle this subject quite well in their books.

Pierreten
A: 

A lambda expression is an anonymous, first-class function. When you declare one, you create a function that is addressable, but can have any number of aliases, just like an object (hence, first-class). You can pass it around in variables and parameters. Javascript can be called a lambda language because all javascript functions have these properties. They can be instantiated, aliased and passed, and don't need to have a name like functions in C do. So, they are anonymous, first-class functions.

Eric Mickelsen
so the main difference, as i see it, is that the lambdas in javascript can, themselves, have properties, whereas in c# they do not. Is that correct?
wcpro
That's correct, but I wouldn't call it the main difference. That difference is mainly a side-effect of dynamic (Javascript) vs. static (C#) typing. When you use a lambda in C#, its type is entirely defined by its signature. The same is true of anonymous methods in Javascript, except that in Javascript, you can add properties to the resulting object after it is instantiated. Also, in Javascript, you'll note that there isn't a real signature, and there are no type constraints - it's duck typed.
Eric Mickelsen
A: 

Lambda isn't a "language" in of itself, as much as it is a part of the C# language. http://msdn.microsoft.com/en-us/library/bb397687(VS.90).aspx

Lambada expressions are "syntatic sugar" that removes a lot of redundant coding.

http://www.rvenables.com/tag/lambda-expressions/ has a real good example of the shortcut lambada provides.

http://www.codeproject.com/KB/cs/DelegatesOMy.aspx has another example of pre/post lambda.

WernerCD
A: 

I'll have a go at your first part of your question. It might be worth reposting the second & third parts as separate questions.

I like to think of lambdas in terms of being functions/procedures that I define like local variables instead of at the module level.

So, let's say I have this code:

public void Run()
{
    var template = "{0} inches is {1} centimetres.";
    Console.WriteLine(template, 2.0, 2.0 * 2.54);
    Console.WriteLine(template, 5.0, 5.0 * 2.54);
}

Clearly I don't want to repeat the expression * 2.54 so I could define a function like this:

private double Inches2Centimetres(double inches)
{
    return inches * 2.54;
}

And my code now becomes:

public void Run()
{
    var template = "{0} inches is {1} centimetres.";
    Console.WriteLine(template, 2.0, Inches2Centimetres(2.0));
    Console.WriteLine(template, 5.0, Inches2Centimetres(5.0));
}

But this separates the function from the calling code and, if this is the only place that I require the calculation, I'm actually hurting maintainability of my code.

I could decide to use a lambda, so I can write this instead:

public void Run()
{
    Func<double, double> inches2Centimetres = inches => inches * 2.54;

    var template = "{0} inches is {1} centimetres.";
    Console.WriteLine(template, 2.0, inches2Centimetres(2.0));
    Console.WriteLine(template, 5.0, inches2Centimetres(5.0));
}

As far as my calling code is concerned, the difference between Inches2Centimetres & inches2Centimetres is the casing of the function name. But for code cleanliness and maintainability, the use of a lambda has given me better encapsulation.

Now since the function is defined as a variable of type Func<...> you can pass lambdas around just like variables.

Here's a good example of where this can be useful: I will often create extension methods for things like database connections to hide the plumbing gumpf so as to leave the essence of the code I'm writing.

public static T[] UsingDataReader<T>(
    this IDbConnection @this,
    string query,
    Func<IDataReader, T> transform)
{
    //...
}

The lamdba in this case, Func<IDataReader, T> transform can then be passed in when I'm calling the function and it only needs to know how to turn the current row into an object of type T. All of the code for opening the connection, executing the reader command, moving between records and closing everything cleanly is neatly handled by the extension method. My calling code is far more succinct.

string[] names = conn.UsingDataReader<string>("select FirstName from People;",
    dr => dr["FirstName"] as string);

I know I've provided a very simplistic answer to your question, but I hope it helps.

Enigmativity
A: 

A function in traditional Lambda calculus was a function that operates on a single value and returns a single value - a unary function. They were also very simple functions that didn't do anything particularly complex (usually mapping one set to another). To do complex work you would chain the functions, so that the output from a first function would be the input to a second function.

Lambdas in C# are just unary functions in the same way. We use them to project, transform, filter or sort data.

Think of a 'Lambda' as a function that takes on parameter and returns a value.

Kirk Broadhurst
+4  A: 

I can address the JavaScript part. Because you can declare anonymous functions in JS (var fn = function(){/* stuff */};, you can also pass those functions as parameters to other functions. In fact, you've already used lambdas if you've ever had to do a custom sort routine. For example:

// Standard sort:
x = [4,3,6,7,1,5,2];
x.sort();

// Custom sort:
y = [
    {'val':4,'name':'four'},
    {'val':3,'name':'three'},
    {'val':6,'name':'six'},
    {'val':7,'name':'seven'},
    {'val':1,'name':'one'},
    {'val':5,'name':'five'},
    {'val':2,'name':'two'},
];
y.sort(function(a,b){ return a.val > b.val ? 1 : -1 });

replace() is another example that takes lambda functions as parameters.

Doing this in your own code is pretty easy, though in practice I never found a circumstance when this couldn't be done more clearly some other way (if anyone else needs to manager your code, you're guaranteed to break their head until they see the lambda).

Here's an example. Say you have a Widget object that produces some form of output. You know it will always produce output, but you don't know what form that output will take. One solution is to pass into the object the method it needs to generate that output. Here's a simple implementation:

First, the Widget itself. Note that Widget.prototype.publish() takes a single parameter, which is your custom formatter:

var Widget = function() {
    var self = this;
    var strPrivateVar = "This is a private variable";
    self.publicVar = "This is a default public variable";
    self.publish = function(f) {
        var fnFormatter = f;
        var strOutput = "The output is " + fnFormatter(self,strPrivateVar);
        return strOutput;
    }
};

Next, your formatters. One gives a brief summary while the other gives the full text:

var fnSummary = function(o,s) {
    var self = o;
    var strPrivateVar = s;
    return strPrivateVar.substr(0,5) + ' ' + self.publicVar.substr(0,5);
}
var fnDetails = function(o,s) {
    var self = o; 
    var strPrivateVar = s;
    return strPrivateVar + ' ' + self.publicVar;
}

And last, your implementation:

var wWidget = new Widget();
wWidget.publicVar = "I have overridden the public property";
var strSummary = wWidget.publish(fnSummary);
var strDetails = wWidget.publish(fnDetails);
console.log(strSummary,strDetails);

This solution means you don't need to alter the wWidget object to get the desired output. Due to scoping issues, you do have to jump through some hoops to get the variables from the object into the publisher methods, but once you do that the rest is easy.

I know there are others on SO that could give a better example, but I hope this helps you.

Andrew
+8  A: 

Let me give you the scoop on what's going on behind the scenes. It is more straightforward than you think.

Suppose you have:

delegate int D(int x);
...
class C
{
    void M(int y)
    {
        int z = 123;
        D d = x=>x+y+z;
        Console.WriteLine(d(10));
        z = 345;
        y = 789;
        Console.WriteLine(d(10));
   }
}

All the compiler does is pretends that you wrote:

delegate int D(int x);
...
class C
{  
    private class Locals
    {
        public int y;
        public int z;
        public int A(int x)
        {
            return x + this.y + this.z;
        }
    }
    void M(int y)
    {
        // Initialize the closure class:

        Locals locals = new Locals();
        locals.y = y;

        // Transform the body so that all usages of y, z and the lambda
        // refer to the closure class:

        locals.z = 123;
        D d = locals.A;
        Console.WriteLine(d(10)); // Calls locals.A(10)
        locals.z = 345;
        locals.y = 789;
        Console.WriteLine(d(10)); // Calls locals.A(10)

    }
}

That's all there is to it. A lambda is just a compact syntax for writing "hoist all the outer local variables used by the lambda into a class, make a method on the class with a given body, and make me a delegate out of that method".

Function closures in JScript work essentially the same way. JScript of course is not a class-based language so the details are slightly different, but the idea is the same. In C#, the newly created delegate object keeps track of the locals class, which has the variable state. In JScript, the newly created function object has a reference to the activation frame of the function which created the closure, which is basically the same information.

The way lambdas are converted to expression trees is rather different, but this should at least get you started in understanding the idea of lambdas.

Eric Lippert
Would it be more precise to instead have `int z = 123;` in a line above `Locals locals = new Locals();` and `locals.z = z;` in place of `locals.z = 123`? The code you have for your demonstration seems a bit off in case z is used somewhere outside the lambda later on in `M`. Or perhaps my proposal makes things worse, because what if y or z are modified between the delegate declaration and the writeline.
Brian
@Brian: It is not *more precise*, it is *incorrect*. The closure captures the *entire variable*, not *the value at the time when the closure is created*. There is no more local variable z; it goes away *entirely*. If z is used somewhere outside the lambda in M then that z also becomes locals.z. *Changes made by the lambda to the state of z are visible outside the lambda*. Again, let me repeat this to make sure it is crystal clear: the closure captures **the variable**, not **its value**. Many people are confused on this point.
Eric Lippert
@Eric Lippert: Then isn't `locals.y = y;` incorrect? And yes, I realize the syntax doesn't allow you to say `locals.y is an alias to y;`
Brian
@Brian: No, it is correct. We cannot make the variable y go away because the local frame did not allocate that variable. That variable is allocated and filled in by the *caller*. Obviously it has to be filled in by the caller; the method doesn't know what parameters it was called with. But we can replace every *usage* of y with locals.y. locals.y has got to have the same value as y, so it is initialized immediately and then y is never read from or written to again, so who cares that it still exists?
Eric Lippert
@Brian: As you note, if we had the ability to say "this field is an alias for this variable" then we'd be done; the closure could just be a collection of aliases. We do not have such a mechanism because the CLR does not allow it. If you build such a mechanism then either the system becomes fragile (because you can store references to dead stack variables) or it becomes inefficient (because you cannot store referenced variables on the stack.) I've updated the code sample to demonstrate the rewrite more clearly.
Eric Lippert
@Eric: My complaint was me being nitpicky about the some minor ambiguity in your example code. Earlier versions had two lines, `locals.y = y;` and `locals.z = 123;`. Without your newly-added comment about transforming new instances of these variables, there was a possible, incorrect interpretation of your example code where locals.y or locals.z (or even only one of the two) worked by capturing the value rather than the variable. This interpretation makes no sense and is totally wrong, but I don't see C# lambdas enough for that interpretation to be immediately rejected.
Brian