OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 10:30 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 10 posts ] 
Author Message
 Post subject: Lambdas in C++
PostPosted: Fri Jan 29, 2021 11:28 am 
Offline
Member
Member

Joined: Fri Nov 22, 2019 5:46 am
Posts: 590
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


Top
 Profile  
 
 Post subject: Re: Lambdas in C++
PostPosted: Fri Jan 29, 2021 11:54 am 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
What difference do you see between a function and a lambda?

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: Lambdas in C++
PostPosted: Fri Jan 29, 2021 11:55 am 
Offline
Member
Member

Joined: Fri Nov 22, 2019 5:46 am
Posts: 590
A lambda is anonymous. A function has a name.


Top
 Profile  
 
 Post subject: Re: Lambdas in C++
PostPosted: Fri Jan 29, 2021 11:57 am 
Offline
Member
Member

Joined: Tue Aug 11, 2020 12:14 pm
Posts: 151
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.


Top
 Profile  
 
 Post subject: Re: Lambdas in C++
PostPosted: Fri Jan 29, 2021 11:57 am 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
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.

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: Lambdas in C++
PostPosted: Fri Jan 29, 2021 12:47 pm 
Offline
Member
Member

Joined: Fri Nov 22, 2019 5:46 am
Posts: 590
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


Top
 Profile  
 
 Post subject: Re: Lambdas in C++
PostPosted: Fri Jan 29, 2021 12:58 pm 
Offline
Member
Member
User avatar

Joined: Fri Oct 27, 2006 9:42 am
Posts: 1925
Location: Athens, GA, USA
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.

_________________
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.


Last edited by Schol-R-LEA on Fri Jan 29, 2021 1:10 pm, edited 3 times in total.

Top
 Profile  
 
 Post subject: Re: Lambdas in C++
PostPosted: Fri Jan 29, 2021 1:01 pm 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
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.

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: Lambdas in C++
PostPosted: Fri Jan 29, 2021 3:32 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
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:
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:
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:
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!


Top
 Profile  
 
 Post subject: Re: Lambdas in C++
PostPosted: Sun Jan 31, 2021 5:11 am 
Offline
Member
Member
User avatar

Joined: Mon Jun 05, 2006 11:00 pm
Posts: 2293
Location: USA (and Australia)
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:
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:
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:
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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 34 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group