Reputation: 401
I was under the impression that writing crisp functions that does just one thing is better than writing a relatively larger function that does more than one thing and enclosing that as a lambda?
Upvotes: 1
Views: 132
Reputation: 5866
Quite often, especially in algorithms in a standard library, there's a need to provide a short function. Some of the obvious examples of that are super-short functions that "tell" the std::sort
how to properly compare two values (say you are sorting a vector of your own type with multiple keys and you want to sort "this time" by one of those keys).
In these cases it used to be required (pre-C++11) to write that short function as a named function. Doing so would generally pollute the name space and to solve this - lambdas were introduced.
This doesn't violate the "one function - one thing" principle as the lambda in this case is just a supporting shortcut for an in-place short code that would otherwise need be put into a standalone named function.
Upvotes: 1
Reputation: 63402
When thinking about the length of a function, it's useful to consider the body of any lambdas inside it to be not part of the length. Imagine to yourself they have been extracted to elsewhere and just referenced.
Having said that, let's distinguish two cases of lambdas:
Virtually required to be defined in-function, as the alternative is creating a class type with an appropriate operator()
and some initialiser. Values of such function types are not really useful outside of the function using them. This is both more boilerplate and less localised, there is no upside.
E.g. given
struct Compound
{
int interesting_member;
std::string uninteresting_member;
};
If you want to find a specific Compound
in a std::vector<Compound>
based on only the value of interesting_member
, you can implement it either
struct CompoundFinder
{
bool operator(const Compound & item) { return item.interesting_member == needle; }
int needle;
}
std::vector<Compound>::iterator find_by_interesting(int needle, std::vector<Compound> & haystack)
{
return std::find_if(haystack.begin(), haystack.end(), CompoundFinder{ needle });
}
Or with a capturing lambda
std::vector<Compound>::iterator find_by_interesting(int needle, std::vector<Compound> & haystack)
{
return std::find_if(haystack.begin(), haystack.end(),
[needle](const Compound & item)
{ return item.interesting_member == needle; });
}
Here it is less clear cut. If you only need a particular function once, it can be simpler to definition a lambda rather than add a name to the enclosing scope that performs the same task.
Upvotes: 0