Lambdas in C++

Programming, for all ages and all languages.
Post Reply
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

Lambdas in C++

Post by PeterX »

AndrewAPrice mentioned using and appreciating lambdas in C++.

Does one really need lambdas when you have functions? What are they good for, as a function is always more self-explanatory?

Greetings
Peter
kzinti
Member
Member
Posts: 898
Joined: Mon Feb 02, 2015 7:11 pm

Re: Lambdas in C++

Post by kzinti »

What difference do you see between a function and a lambda?
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

Re: Lambdas in C++

Post by PeterX »

A lambda is anonymous. A function has a name.
sj95126
Member
Member
Posts: 151
Joined: Tue Aug 11, 2020 12:14 pm

Re: Lambdas in C++

Post by sj95126 »

I suppose you could make a few arguments: one, if the lambda is specific to its particular use, it's self-contained and localized. Sort of the same way you might declare local variables within a block or loop, rather than at the beginning of a function. Second, it can serve as an implicit definition that the lambda code is inline, which might result in more efficient code. (for example, the compiler might skip the steps to move around the function arguments to comply with the ABI)

Personally, while I appreciate what lambda's do, it's one of those things that's easy to overuse and abuse. If using a lambda means you now have 2-3 lines of code instead of 1, you're probably doing it wrong.
kzinti
Member
Member
Posts: 898
Joined: Mon Feb 02, 2015 7:11 pm

Re: Lambdas in C++

Post by kzinti »

Bingo. The lambda function doesn't have a name.

So the only other difference then is that you can't reuse the anonymous lambda since it doesn't have a name.

The main argument for it is that it makes some code more readable and take less lines of code.

But lambdas and normal functions are essentially the same.
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

Re: Lambdas in C++

Post by PeterX »

kzinti wrote:The main argument for it is that it makes some code more readable and take less lines of code.
Concerning readabilty I think the opposite way. But maybe you are right.

Greetings
Peter
User avatar
Schol-R-LEA
Member
Member
Posts: 1925
Joined: Fri Oct 27, 2006 9:42 am
Location: Athens, GA, USA

Re: Lambdas in C++

Post by Schol-R-LEA »

The real advantage of lambdas doesn't really apply to C++, IMAO. The real advantage of lambdas is in using them to generate runtime code, and that simply isn't feasible in C++ in the ways it is in, say, Common Lisp or Haskell. Unless you can compile or interpret the code at run time, lambdas don't really help much in general.

Note that lambdas have a number of important roles in both computability theory and compiler theory, and Scheme is essentially built out of lambdas (though it was even more so in its original form), but that's separate from the practical uses in a language such as C++.

Also, some other languages which have lambdas use them in specific and limited ways, which make them useful for language-specific purposes - such as Python, where it is useful in list comprehensions, or Java, where IIRC they can be used as in lieu of inner functions for callbacks and event handlers.

This isn't to say they have no place in C++; I honestly don't know enough about how they are used there to say. I can certainly see uses for, say, functors (which are functions manipulated at runtime through pointers) and callbacks (where an anonymous functor may be passed as the callback pointer). Perhaps someone such as Solar can speak on it with more detail and authority.
Last edited by Schol-R-LEA on Fri Jan 29, 2021 1:10 pm, edited 3 times in total.
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.
kzinti
Member
Member
Posts: 898
Joined: Mon Feb 02, 2015 7:11 pm

Re: Lambdas in C++

Post by kzinti »

PeterX wrote:Concerning readabilty I think the opposite way. But maybe you are right.
I've always seen people on both sides of this. Which one is more readable ends up being different for each one of us.
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: Lambdas in C++

Post by nullplan »

Lamdas in C++ are used in places where callback code would be needed so that you don't need to decouple a class or function.

Say you have a collection of structures. You want to find an element of the collection where one data field matches a given parameter. Say, a list of employees and you are looking for some SSN. You can write

Code: Select all

struct Employee {
  std::string name;
  Department department;
  std::string SSN;
  /* ... */
};
void do_something_with(std::string SSN)
{
  for (auto it = employees.begin(); it != employees.end(); ++it)
    if (it->SSN == SSN)
      break;
  /* ... */
}
But recently, C++ has been on something of a crusade against loops. We've all written more than enough loops in our lives. Now, we could use std::find_if to find the wayward employee, but that requires a predicate. Which we can do like this:

Code: Select all

class matchesSSN {
  const std::string &SSN;
  public:
    explicit matchesSSN(const std::string &SSN) : SSN(SSN) = default;
    bool operator()(const Employee& emp) { return emp.SSN == SSN; }
};
void do_something_with(std::string SSN)
{
  auto it = std::find_if(employees.begin(), employees.end(), matchesSSN(SSN));
That is better, but it requires us to create a whole new class, just for a single purpose. Reuse of that class is going to be very limited. It is essentially boilerplate. However, with lambdas:

Code: Select all

void do_something_with(std::string SSN)
{
  auto it = std::find_if(employees.begin(), employees.end(), [SSN](const Employee& emp){ return emp.SSN == SSN; });
And boom, no more loop and no more temporary class with weird semantics.

You might not see the appeal with find_if, but make it remove_if and suddenly it is useful.
PeterX wrote:Does one really need lambdas when you have functions?
Lamdas can capture. Functions cannot. You can create functors to make a function that captures some state, but for single-use items, this is typically less than ideal.

I would bring up the example of qsort(), where it is always a hassle to uncouple a comparator from the rest of the code, often just for a single use, and how a capture-less lambda can be used there, but then, C++ has std::sort.
Carpe diem!
User avatar
AndrewAPrice
Member
Member
Posts: 2300
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: Lambdas in C++

Post by AndrewAPrice »

Lambdas can make code more readable and flow more sequentually.

There is also a lot of power in capturing closures.

There are three common scenarios I use lambdas in production code: (where I deal with massive amounts of data and latency Is a concern.)

1) I want to iterate over a set, and want to call a handler inline rather than allocate and return collections, especially if it's just used temporarily. E.g. instead of:

Code: Select all

std::vector<Document> FetchInterestingDocuments() {
  std::vector<DataStoreFormat> data_store_documents = FetchDocumentsFromBackend();
  std::vector<Document> all_documents = ParseDataStoreDocuments(data_store_documents);
  std::vector<Document> interesting_documents;
  for (const Document &document : all_documents) {
    if (IsinterestingDocument(document)) {
      interesting_documents.push_back(document);
  }
  return interesting_documents;
}
You could do:

Code: Select all

void ForEachInterestingDocument(const std:function<void(const Document&>)& on_each_interesting_document) {
  ForEachDataStoreDocument([&on_each_interesting_document] (const DataStoreDocument& data_store_document) {
    Document document = ParseDataStoreDocument(data_store_document);
    if (IsInterestingDocument(document)) {
      on_each_interesting_document(document);
    }
  }
}
2) I'm building a function, especially one that will execute many times (e.g. for every 100,000 items in the data store) and I can do some precalculation and pass it into the lambda, e.g.

Code: Select all

std::function<bool(const Document&)> BuildIsInterestingDocumentFunction(const Request& request) {
  StructuredQuery structured_query = ParseRawQuery(request.RawQuery());
  switch (structured_query.Type()) {
    case SIMPLE_QUERY: {
      SimpleQueryEvaluator evaluator(structured_request);
      return [evaluator](const Document& document) {
        return evaluator.IsInterestingDocument(document);
      }
    case COMPLEX_QUERY: {
      ComplexQueryEvaluator evaluator(structured_request);
       return [evaluator](const Document& document) {
        return evaluator.IsInterestingDocument(document);
    }
    default:
      return [](const Document&) { return false; };
  }
}
Now can call BuildIsInterestingDocumentFunction once per server request but call the returned function for each of the hundreds of thousands of documents.

3) To put handing/callbacks inline, especially when they are small, if it increases readability by avoiding the reader from having to scroll up and down the file to see what some small, trivial handler does.

----
As in all things programming, there are multiple ways to do things and you can avoid lambdas. I use lambdas if it helps readability. I hate overly verbose code (e.g. the Java practice of making every handler a class and putting it into its own file.) I like code that reads sequentially.
My OS is Perception.
Post Reply