[Development] RFC: lambda or lambda return from lambda?
Marc Mutz
marc.mutz at kdab.com
Mon Feb 1 11:08:54 CET 2016
Hi,
We're seeing increasing use of lambdas in dev, and I'm a bit unhappy about the
result.
E.g. (not picking on Anton here, I have done the same before):
auto firstEqualsName = [&name](const QPair<QByteArray, QByteArray> &header)
{
return qstricmp(name.constData(), header.first) == 0;
};
fields.erase(std::remove_if(fields.begin(), fields.end(),
firstEqualsName),
fields.end());
This is one way to write a unary predicate. But it hides the fact that the
predicate depends on the parameter 'name' (an argument to the function this
lambda is defined in).
With classical function objects, one would have written - at the call site:
fields.erase(std::remove_if(fields.begin(), fields.end(),
FirstEquals(name)),
fields.end());
See the difference?
Now, we don't want to go back and write function objects for one-time use, but
it would be nice to have this explicit syntax, would it not?
One way to have this with lambdas is to write a lambda that returns a lambda.
We can do this, because auto return type deduction works for lambdas already
in C++11, unlike for normal functions. With this, the above would become (hold
tight):
auto firstEquals = [](const auto &name) {
return [&name](auto header) { return qstricmp(header.first, name) == 0; };
}
where I used auto and dropped the const-& argument passing only for
exposition, to get it onto a single line.
fields.erase(std::remove_if(fields.begin(), fields.end(),
firstEquals(name)),
fields.end());
So, where to put the ugliness: on the definition of the lambda, or the call
site? (Note that "if you use this lambda more than once, then X" is not a good
answer, because you shouldn't use lambdas more than once. But with the lambda-
returning-lambda, you could actually reuse them:
// at global scope:
auto firstEquals = [](const auto &name) {
return [&name](auto header) { return qstricmp(header.first, name) == 0; };
}
// use in several functions - always the same type
Whereas without the outer lambda, each use would create a new type, and
potentially duplicate code (same problem as QStringLiteral, and the same
soultion, really: wrap them in a function, except for lambdas, because of the
unnameable return type, we need to use another lambda instead of a classical
function).
So, which one to use?
Thanks,
Marc
--
Marc Mutz <marc.mutz at kdab.com> | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts
More information about the Development
mailing list