What are lambda Expressions? And what’s the point of using them?

Asked

Viewed 20,675 times

58

When I started using LINQ I saw I could use the famous lambda Expressions.

Until I know that x => x * x is a lambda Expression, but I could not explain to a colleague what they really are, and what is the advantage of using them.

So I ask you:

What are lambda Expressions? And what’s the point of using them?

7 answers

48


What are lambda expressions?

Lambda expressions are those of type A going to B, meaning primarily a transformation. In C#, there are constant, and multiparametrized Lambdas.

In C#, a lambda expression can be converted to:

  • one Delegate: is a compiled method, which can be executed, and passed as if it were a variable to whoever needs it. Also called anonymous methods, because they do not have their own identifier.
  • one Expression<> representing a tree of expressions denoting in data structure form the transformation representing the expression lambda.

Use in the form of Delegate

When converted to a delegate, the lambda can be passed as if it were a variable. A lambda produces a delegate of a specific type depending on the context in which it is created.

The calls below generate delegates of different types:

// delegate gerado do tipo Func<string, bool>
Func<string, bool> func = s => s == null;

// delegate gerado do tipo Predicate<string>
Predicate<string> pred = s => s == null;

Thus each delegate of distinct type can be passed as if it were a common variable, being possible to call these methods so:

pred("string to test");

All delegates, regardless of the specific type, inherit from the class Delegate.

Closures in delegates

Lambdas can present in its contents, variables present in the method that builds it, trapping this variable, in the form of a reference to it. This is also possible when building inline delegates.

int i = 0;
Action incrementa = () => i++;
incrementa();
// neste ponto a variável i, terá seu valor incrementado

This is a very powerful tool, and also dangerous, especially when used in loops, using the value of the iteration variable.

var listFunc = new Func<int>[10];
for (int it = 0; it < 10; it++)
    listFunc[it] = () => it;
// todos os elementos de listFunc retornam 10
// pois a variável it, neste ponto vale 10,
// e todos os delegates referenciam a mesma variável

Use in the form of Expression

When talking about lambda expression, it is common to pass beaten by this way of using them, but that is widely used by frameworks like the EntityFramework and the MVC, both from Microsoft.

LINQ supports the interface IQueryable, which is based on the use of data structure transforms, which it analyzes in order to create a query that can be executed in the database.

Just as these libraries do, it is possible to read this data structure generated from a lambda expression, using the classes present in the namespace System.Linq.Expressions.

In addition, these Ambles in the form of Expression can be copied and modified, and then compiled, being one of the ways to be generated dynamically executable code. It is also possible to create an expression tree from scratch, dynamically generating integer methods, using the method Compile, present in the class Expression<T>.

Closures in expression trees (Expression Trees)

Expression Trees can, as well as delegates, have references to context variables in their code. Thus, the reference to the variable is trapped in a node of the expression tree, which allows reading the value of that variable, and maintaining the semantics when compiling this expression tree.

  • Miguel, closures are not unique to lambda expressions. Anonymous methods also have this feature.

  • @The way I said, it really looked like this is the only way to make closures... I’ll edit it. Thanks!

  • Great explanation, Miguel.

24

In essence, the advantage (in C#) of using them is being able to carry small functions as values.

In essence. Because they involve several other advantages.

In fact, x => x * x is not ONLY a Lambda Expression, it is also known as an anonymous function, and can thus be used as any other function. You can even declare it so:

Func<int, int> aoQuadrado = x => x * x;

And I could run it on a list, for example:

Enumerable.Range(1, 101).Select(aoQuadrado).ToList();

What would produce a Ienumerable with the squares of numbers from 1 to 100 (Enumerable.Range is exclusive, that is, does not include the last number -- in this case, 101 -- in its operations).

This is equivalent to this (which is essentially the same thing, imperative rather than functional):

int AoQuadrado(int n)
{
    return n * n;
}

var quadrados = new List<int>();
for (int i = 0; i < 101; i++) quadrados.Add(AoQuadrado(i));

By the way, both methods and anonymous functions (or lambda) are functions, IE, you could do this too:

int AoQuadrado(int n)
{
    return n * n;
}

var quadrados = from i in Enumerable.Range(1, 101).Select(AoQuadrado).ToList();

For that is perfectly valid:

int AoQuadrado(int n)
{
    return n * n;
}

Func<int, int> aoQuadrado = AoQuadrado;

This is usually called "first-class functions". It is the possibility to use functions as values, and thus be able to carry them more easily.

In short: Their main use is to be able to carry small functions as values, I would say.

  • It is worth highlighting other aspects of lambda expressions, such as Expression Trees, the generation of closures, among others, as described in my reply.

  • 2

    @Miguelangelo That’s right, but my answer was focused on their use in C# (and LINQ, as the author of the question appeared to be focusing on). Not that Expression Trees and Closures are not important (especially Closures that are a very important concept), but I think they are concepts that go far beyond the scope of the question.

  • 1

    I don’t think it’s the focus, mainly because of LINQ... LINQ to Objects uses Lambdas in the form of delagates, but LINQ to Entities, LINQ to SQL among others use Lambdas in the form of Expression Trees.

  • @Miguelangelo It is a valid way to see. As I quoted in the chat, my answer was a dart and his a bowling ball. They both hit the target of the question.

  • Andre, you’re confusing lambda expressions with delegates that are one of the possible translations. As @Miguelangelo pointed out, they can also be translated into expression trees.

13

A lambda expression is a concise way of declaring a function or subroutine. In an object-oriented world, it’s very similar to an object that has one method.

There are two main advantages of using a lambda expression instead of a function or defined separator method:

  1. Simplicity. Why give a name to something that will only be used once?

  2. Lexical scope. Lambda functions can automatically use all variables of the current scope. For example:

    int y = 10;
    Func<int,int> f = (x => x + y);
    

    f is a function that adds 10 to its argument. To do something equivalent using classes, we would need to create a new class, create a "y" field in this class, initialize this field in the class constructor and pass 10 as parameter when creating the f. Using anonymous functions this all comes free.

  • +1 good response - you provided the information requested, without prolonging in detail. And the comparison with "an object of one method" is very relevant - before we had Ambles in C#, that’s exactly what we did.

11

In general lambda means passing a function as argument to another function (definition given for Javascript, and extends to all functional languages):

In free translation:

Lambda basically means to use a function as an argument in one call to the other function. Lambda is a popular buzzword in functional programming and is widely used. The worst thing is, it’s used as if everyone knew its real meaning. So if you see something like "Here we’ll use a lambda expression," it means they’ll just be passing a function as an argument.

Visually, in psuedo-code, Lambda is represented by the symbol λ, the 11th letter of the Greek alphabet. You can also see variable names like lambda to indicate that it will receive a function.

http://www.hunlock.com/blogs/Functional_Javascript#quickIDX3

The drawback in using them is to be able to have the lambda function performed at another time (That’s how callbacks work in Javascript).

For example, if it is necessary to compute in/after a certain asynchronous event (such as an http request) is executed, we use a lambda expression (callback) in the function. Asynchronous events are important in the sense that they do not bar the program from running :)

8

William, this is a good question and it would require a very long answer. It was trying to be brief, and for that was to leave out a lot, all right?

What are lambda Expressions?

They are, by definition, anonymous functions. I like to think of lambda expressions as math functions. You have the input parameters and the body of the function, for example: f(x) = x * 2

On the left side you define what the function receives, on the right side what it does.

And what’s the point of using them?

IMHO, the biggest advantage is being able to send functions as arguments for methods. The biggest example of this is in Linq, as you commented. See:

cidades.Where(x => x.Nome == "Florianópolis");

Let’s see the method signature Where:

public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);

The first argument is necessary because it is an Extension method, so let’s put it aside for now. But look at the second. It’s an expression where her type is the type of collection and she returns a Boolean. In this way, any lambda expression that conforms to these restrictions can be sent as a parameter.

The nice thing about this is that you can use all this potential in your code, you don’t have to leave it just in the framework.

6

Lambda expressions are nothing more or less than types of methods that you encode in summary form, without specifying the entire structure of a method. In fact, they return a reference to that encoded functionality.

This is very common in LINQ, because when you filter a collection you basically want to pass a method that decides whether or not an object should be among the filtered ones. For example, suppose you have a collection of objects of the following class

public class Cliente
{
    public int ClienteID { get; set; }
    public string Nome { get; set; }
    /* Outros membros */
}

And then you want only those who possess ClienteID pair for example. Then you use LINQ as follows:

var clientesFiltrados = listaClientes.where(verificaIdPar);

That one verificaIdPar points to a method that can verify whether a ClienteID is par. But think about it: to code this method normally, you would have to put it in a class and everything, referencing it and then passing it to the where and I’d hardly use it again. For this lambda expressions simplify your life, you can simply put a lambda expression in place, which it returns a reference to the method that has the functionality described in the lambda expression.

Also note that you can reference lambda expressions by delegate type variables. And that’s actually what these LINQ methods do: they expect a delegate to point to a method that filters, selects, or any other operation, and then for simplicity we use lambda expressions.

5

I believe that the concept is more important than the way it is implemented.

Lambda expressions are functions, the way we learn in high school. For a given value of X, we ALWAYS get a certain result Y. That is, given an X value, we always get the SAME value of Y. This behavior of an expression/function is called immutability, extremely important in functional languages, and that in programming minimizes the bugs related to side effects and allows to work with parallel programming and distributed more easily.

When a programming language implements the use of lambda expressions, it allows it to be treated as a value. That is, the function/expression can be placed in a variable, passed as a parameter, and can normally be used in loops, lists of values and the like, depending on how the language implements the resource.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.