Lambdas in C++
Lambdas in C++
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
Does one really need lambdas when you have functions? What are they good for, as a function is always more self-explanatory?
Greetings
Peter
Re: Lambdas in C++
What difference do you see between a function and a lambda?
Re: Lambdas in C++
A lambda is anonymous. A function has a name.
Re: Lambdas in C++
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.
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.
Re: Lambdas in C++
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.
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.
Re: Lambdas in C++
Concerning readabilty I think the opposite way. But maybe you are right.kzinti wrote:The main argument for it is that it makes some code more readable and take less lines of code.
Greetings
Peter
- Schol-R-LEA
- Member
- Posts: 1925
- Joined: Fri Oct 27, 2006 9:42 am
- Location: Athens, GA, USA
Re: Lambdas in C++
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.
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.
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.
Re: Lambdas in C++
I've always seen people on both sides of this. Which one is more readable ends up being different for each one of us.PeterX wrote:Concerning readabilty I think the opposite way. But maybe you are right.
Re: Lambdas in C++
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
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:
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:
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.
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.
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;
/* ... */
}
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));
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; });
You might not see the appeal with find_if, but make it remove_if and suddenly it is useful.
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.PeterX wrote:Does one really need lambdas when you have functions?
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!
- AndrewAPrice
- Member
- Posts: 2299
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
Re: Lambdas in C++
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:
You could do:
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.
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.
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;
}
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);
}
}
}
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; };
}
}
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.