13

The reason for lambda expressions is implicitly generate function objects in a "more convenient way". As you can see from the example below, it is not only less convenient and longer, but also has a confusing syntax and notation.

Are there any uses of this, where it actually makes code more readable?

cout << count(vec, [&](int a){ return a < x; }) << endl;  // lambda
cout << count(vec, Less_than<int> (x)) << endl;           // normal functor def-n
Oleksiy
  • 37,477
  • 22
  • 74
  • 122
  • 3
    The lambda version is not longer. The non-lambda one is incomplete, since we don't have the definition of `Less_than`. – Benjamin Lindley Aug 11 '13 at 02:04
  • How is that `Less_than (x)` a "normal function definition"??? Judging by your first example, it looks like you need to bind the value of `x` to a two-parameter comparator functor, converting it into a single-parameter comparator. This is already functionality that goes far beyond "normal function definition". – AnT stands with Russia Aug 11 '13 at 02:10

2 Answers2

24

It is more readable because it places the implementation of the function right into the spot where it is called, thus keeping the natural top-to-bottom flow of code unchanged.

You see, ordinary functions have their pros and cons. On the one hand, functions help reduce repetitions in the code, this making the code more structured and more readable. On the other hand, functions break the natural flow of code and transfer control to a completely different location. This can reduce the readability for rather obvious reasons: it is like reading a book that is riddled with nested forward and backward references.

So, in order to properly take advantage of the properties of ordinary functions, one should use them to implement well-thought-through, complete and isolated abstractions. That way ordinary functions will improve the readability of the code.

But for small "disposable" one-time-use utility code, ordinary functions don't work so well. They can actually makes the code significantly less readable. This is where lambda functions come in. They allow one to inject that disposable utility code straight into the point of the call, where it is necessary.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 2
    An additional point is that lambda functions can access variables directly which are within scope in the parent context (in this case, the lambda could access "vec" directly if needed, for example.) This is part of the utility of not having to make a separate function. – Brad Peabody Aug 11 '13 at 02:06
  • 2
    @AnT so if we summarize, enhancing readability is the main benefit of lambda expressions. By putting the logic within the caller function and reducing "disposable" functions, that's it? Pardon me for my ignorance, I am still striving to see some distinguished utility of lambda expressions, if at all there are any! – Yogesh Jun 11 '19 at 10:01
4

The lambda expression exists to simplify code. This:

auto fun = []() { return; };

Is replaced by the compiler with:

// Namespace scope
struct __lambda_1 {
    void operator()() { return; }
};

// local scope
__lambda_1 fun{};

This is the primary motivation for the lambda syntax: To replace traditional function objects with an easier to read anonymous function declared at the site where it is needed, rather than having a separate function object that must be declared in another scope. It is not merely to replace named function objects.

Indeed, the standard library includes a number of named function objects like std::unary_function and things like std::less. But these objects have limited utility and cannot take on every potential role that a lambda would.

So, yes, it can make code substantially more readable, by placing code that the standard library doesn't provide precisely where it's required, without polluting your code with dozen-line structs and polluting your namespace with names you'll likely use no more than once or twice.

greyfade
  • 24,948
  • 7
  • 64
  • 80