[Boost] [Lambda2] Review starts Monday March 22, 2021 to March 31, 2021
The Boost formal review of the Lambda2, authored by Peter Dimov, starts Monday, March 22, 2021 to March 31, 2021 (inclusive). Documentation: https://pdimov.github.io/lambda2/doc/html/lambda2.html Source: https://github.com/pdimov/lambda2/ Lambda2 is a simple, but functional, C++14 lambda library. It takes advantage of the fact that the standard <functional> header already provides placeholders _1, _2, _3, and so on, for use with std::bind, and function objects such as std::plus, std::greater, std::logical_not, and std::bit_xor, corresponding to arithmetic, relational, logical and bitwise operators. Please provide in your review information you think is valuable to understand your choice to ACCEPT or REJECT including Lambda2 as a Boost library. Please be explicit about your decision (ACCEPT or REJECT). Some other questions you might want to consider answering: - What is your evaluation of the design? - What is your evaluation of the implementation? - What is your evaluation of the documentation? - What is your evaluation of the potential usefulness of the library? - Did you try to use the library? With which compiler(s)? Did you have any problems? - How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? - Are you knowledgeable about the problem domain? More information about the Boost Formal Review Process can be found at: http://www.boost.org/community/reviews.html The review is open to anyone who is prepared to put in the work of evaluating and reviewing the library. Prior experience in contributing to Boost reviews is not a requirement. Thank you for your efforts in the Boost community. They are very much appreciated. Peter is often available in the CppLang Slack #boost channel should you require any clarification not covered by the documentation. I am not frequently available in the Slack channel, but I'll certainly pay attention to the discussions. Please don't hesitate to ping me if needed. Cheers, --Joel de Guzman
On 3/21/21 7:35 PM, Joel de Guzman via Boost wrote:
The Boost formal review of the Lambda2, authored by Peter Dimov, starts Monday, March 22, 2021 to March 31, 2021 (inclusive).
Documentation: https://pdimov.github.io/lambda2/doc/html/lambda2.html Source: https://github.com/pdimov/lambda2/
I have a really dumb question about this. Consider the count_if example. I understand how example works. But I can't figure out where the parameter _1 gets filled in. So I think that the count_if example should be completed with a small bit of code which uses the newly count_if function. Robert Ramey
On 22/03/2021 5:48 pm, Robert Ramey wrote:
I have a really dumb question about this. Consider the count_if example. I understand how example works. But I can't figure out where the parameter _1 gets filled in. So I think that the count_if example should be completed with a small bit of code which uses the newly count_if function.
The _1 parameter is filled in by std::count_if itself (in this case, using each element of the passed iterators). That's the point of a lambda, so I'm not quite sure what you're unclear on. This is not creating a "count_if" function, if that's what you thought; it is a complete example including both definition and usage. Having said that, I do think the docs could benefit by having some "compare and contrast" examples -- i.e. showing how each of those examples would have been implemented using C++11 lambdas or std::bind instead (and thus demonstrate the syntactic benefits of the library).
On 3/21/21 11:48 PM, Gavin Lambert via Boost wrote:
On 22/03/2021 5:48 pm, Robert Ramey wrote:
I have a really dumb question about this. Consider the count_if example. I understand how example works. But I can't figure out where the parameter _1 gets filled in. So I think that the count_if example should be completed with a small bit of code which uses the newly count_if function.
The _1 parameter is filled in by std::count_if itself (in this case, using each element of the passed iterators). That's the point of a lambda, so I'm not quite sure what you're unclear on. This is not creating a "count_if" function, if that's what you thought; it is a complete example including both definition and usage.
Having said that, I do think the docs could benefit by having some "compare and contrast" examples -- i.e. showing how each of those examples would have been implemented using C++11 lambdas or std::bind instead (and thus demonstrate the syntactic benefits of the library).
OK - I see this now. I knew is something dumb. I haven't needed lambdas
much in the work I've done. I think the following as an example
#include
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
On 3/21/2021 10:35 PM, Joel de Guzman via Boost wrote:
The Boost formal review of the Lambda2, authored by Peter Dimov, starts Monday, March 22, 2021 to March 31, 2021 (inclusive).
Documentation: https://pdimov.github.io/lambda2/doc/html/lambda2.html Source: https://github.com/pdimov/lambda2/
Lambda2 is a simple, but functional, C++14 lambda library. It takes advantage of the fact that the standard <functional> header already provides placeholders _1, _2, _3, and so on, for use with std::bind, and function objects such as std::plus, std::greater, std::logical_not, and std::bit_xor, corresponding to arithmetic, relational, logical and bitwise operators.
Please provide in your review information you think is valuable to understand your choice to ACCEPT or REJECT including Lambda2 as a Boost library. Please be explicit about your decision (ACCEPT or REJECT).
Some other questions you might want to consider answering:
- What is your evaluation of the design? - What is your evaluation of the implementation? - What is your evaluation of the documentation? - What is your evaluation of the potential usefulness of the library? - Did you try to use the library? With which compiler(s)? Did you have any problems? - How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? - Are you knowledgeable about the problem domain?
More information about the Boost Formal Review Process can be found at: http://www.boost.org/community/reviews.html
The review is open to anyone who is prepared to put in the work of evaluating and reviewing the library. Prior experience in contributing to Boost reviews is not a requirement.
Thank you for your efforts in the Boost community. They are very much appreciated.
Peter is often available in the CppLang Slack #boost channel should you require any clarification not covered by the documentation. I am not frequently available in the Slack channel, but I'll certainly pay attention to the discussions. Please don't hesitate to ping me if needed.
My first reaction, after quickly looking at the submission, is what does this library offer that the original lambda library, which appears to have a much larger amount of functionality than this lambda2 library, not offer ? Also there is the Phoenix library, which also offers an even greater amount of function object and lambda-like functionality, of which the review manager is the main author I believe. Is it basically so that the programmer can easily interface with the std::bind/std::function classes with the lambda2 placeholders, whereas the C++03 libraries don't have this possibility wit their placeholders ? Please note that I am certainly not against adding Boost libraries that target similar functionality. I just do not understand the motivation for lambda2 other than that it is a C++14 library. I just did not get what being a C++14 library, as opposed to the older C++03 libraries I mentioned, gives the programmer who uses it. I think such an explanation would be welcome somewhere amidst the lambda2 documentation. I also could not decipher what in the world "All operators defined in the subsequent sections only participate in overload resolution if at least one of their operands is such that for its unqualified type T, the expression std::is_placeholder<T>::value || std::is_bind_expression<T>::value is true" means in practical terms. I I see no 'T' s in the subsequent sections, and am just confused.
Edward Diener wrote:
My first reaction, after quickly looking at the submission, is what does this library offer that the original lambda library, which appears to have a much larger amount of functionality than this lambda2 library, not offer ? Also there is the Phoenix library, which also offers an even greater amount of function object and lambda-like functionality, of which the review manager is the main author I believe.
Purely from a user perspective, what this library offers is being a lightweight, single header dependency, and...
Is it basically so that the programmer can easily interface with the std::bind/std::function classes with the lambda2 placeholders, whereas the C++03 libraries don't have this possibility wit their placeholders ?
... indeed, a way to port boost::bind code that uses its operators to std::bind, something that comes up from time to time as projects are modernized.
From a different perspective, another goal of the submission is to gather experience and provide a tested and widely available implementation for an eventual proposal to add this functionality to the standard. (Better late than never.)
On 3/22/21 9:43 AM, Peter Dimov via Boost wrote:
Edward Diener wrote:
My first reaction, after quickly looking at the submission, is what does this library offer that the original lambda library, which appears to have a much larger amount of functionality than this lambda2 library, not offer ? Also there is the Phoenix library, which also offers an even greater amount of function object and lambda-like functionality, of which the review manager is the main author I believe.
Purely from a user perspective, what this library offers is being a lightweight, single header dependency, and...
This should not be under appreciated! I've been working for a boost-bigoted company for the last 5 years and generally limited to C++11 until this month. Having access to Peter's minimal-dependency header-only libraries of late have been a boon to my efforts to modernize our code base. While developers here bristle at bringing in all of boost, there have been no complaints on bringing in mp11, or even the non-boost asio distribution.
pon., 22 mar 2021 o 16:44 Peter Dimov via Boost
My first reaction, after quickly looking at the submission, is what does
library offer that the original lambda library, which appears to have a much larger amount of functionality than this lambda2 library, not offer ? Also there is the Phoenix library, which also offers an even greater amount of function object and lambda-like functionality, of which the review manager is the
Edward Diener wrote: this main
author I believe.
Purely from a user perspective, what this library offers is being a lightweight, single header dependency, and...
Is it basically so that the programmer can easily interface with the std::bind/std::function classes with the lambda2 placeholders, whereas the C++03 libraries don't have this possibility wit their placeholders ?
... indeed, a way to port boost::bind code that uses its operators to std::bind, something that comes up from time to time as projects are modernized.
From a different perspective, another goal of the submission is to gather experience and provide a tested and widely available implementation for an eventual proposal to add this functionality to the standard. (Better late than never.)
My opinion so far is that there is not enough motivation to warrant the addition of this library into Boost. First, the design goals, or the purpose, of the library is not clearly defined. Is the goal that tandem std::bind + Boost.Lambda2 should be a replacement over boost::bind and Boost.Lambda? If so, in the current form of the library the goal will not be satisfied, because current Boost.Lambda offers quite more things. Just look at the motivating examples of Boost.Lambda: https://www.boost.org/doc/libs/1_75_0/doc/html/lambda/using_library.html In particular, the usage of assignment or function constant(). Boost.Lambda2 will not work as a drop-in replacement for Boost.Lambda. For a moment I thought that the goal is to have a cooler syntax for the current standard arithmetic function objects, such as std::plus, std::multiplies. But the advantage is dubious. You gain a few characters, but you pay the cost of * employing a different library * messy error messages * no debugger support The suggestion that we would enable constructs like `std::bind(&Employee::name, e1) < std::bind(&Employee::name, e2)`also doesn't seem like a good motivation. std::bind only works well when it is used for binding arguments to functions. Overusing it for implementing lambdas made sense in C++03, because there was no other way. Now with generic lambdas it can only be considered a bad (or at least controversial) practice. I am far from imposing my programming style on others. But promoting a programming style like this through the inclusion into Boost seems too much. My vision of Boost is that it should support certain programming styles that are considered good, but not any programming style. Regarding the implementation, on the other hand, it is as elegant as a library implementation could ever be. It is extremely short! (78 lines, including whitespace, header guards, and copyright notice). Regards, &rzej;
Andrzej Krzemienski wrote:
First, the design goals, or the purpose, of the library is not clearly defined.
The goals of the library are - Give people the choice of using an abbreviated lambda syntax that is able to express simple operations in fewer characters; - Bring std::bind to parity with boost::bind feature-wise so that porting is easier; - Prepare a proposal to extend the standard with these same additions by gathering experience in Boost first.
Is the goal that tandem std::bind + Boost.Lambda2 should be a replacement over boost::bind and Boost.Lambda? If so, in the current form of the library the goal will not be satisfied, because current Boost.Lambda offers quite more things.
This doesn't make it useless. When porting "operator-enhanced" boost::bind, or Boost.Lambda, code, you need to go over all the uses and change them into language lambdas. This is routine mechanical work that as a result is highly error-prone and without good test coverage, mistakes can easily pass review because of the repetitive nature of the diff. It's much better if you could port at least some of the uses without making changes beyond replacing boost:: with std::, and adding/changing the using directive. It's not necessary to be able to port _all_ uses without any changes; a portion is enough to reduce the error rate significantly. And if you're going to ask what's the point of porting from one Boost library to another, the difference is that it's much easier to "vendor" a single short header.
For a moment I thought that the goal is to have a cooler syntax for the current standard arithmetic function objects, such as std::plus, std::multiplies. But the advantage is dubious. You gain a few characters, but you pay the cost of * employing a different library * messy error messages * no debugger support
This could be true, but it has nothing to do with the library lacking clarity of purpose.
The suggestion that we would enable constructs like `std::bind(&Employee::name, e1) < std::bind(&Employee::name, e2)`also doesn't seem like a good motivation.
As explained, this is only an issue when porting boost::bind code using these constructs. You obviously aren't going to use this in new code because the equivalent language lambda is shorter (not by much) and clearer.
Peter Dimov wrote:
The goals of the library are [...] - Prepare a proposal to extend the standard with these same additions by gathering experience in Boost first.
Am I correct in thinking that this functionality could have been added to the standard library when std::bind was added in C++11, except that it requires something in the core language that was not added until C++14 ? If not, what is the reason why this was not added when std::bind was added? (I've failed to locate any pre-C++11 WG21 papers about std::bind.) Regards, Phil.
Phil Endecott wrote:
Peter Dimov wrote:
The goals of the library are [...] - Prepare a proposal to extend the standard with these same additions by gathering experience in Boost first.
Am I correct in thinking that this functionality could have been added to the standard library when std::bind was added in C++11, except that it requires something in the core language that was not added until C++14 ?
Return type deduction makes it easier to write, and the function objects in <functional> acquired their <void> forms in C++14, but it's possible to make this work in C++11 as well.
If not, what is the reason why this was not added when std::bind was added? (I've failed to locate any pre-C++11 WG21 papers about std::bind.)
I didn't propose it. :-)
Hello Y'all, Thank you all who participated in the review of Lambda2 and thank you Peter for submitting the library. Boost.Lambda2 is now officially accepted into Boost. Accept: 4 Conditional Accept: 1 Reject: 1 There was initially a single reject, but was later changed to Conditional Accept with the condition that: ---> Lambda2 provides its own placeholders instead of importing the standard ones. The review discussion touched on these pros and cons: Pros: - It's simple, clean, and elegant. - lightweight, single header dependency - Involves less typing Cons: - lambda and phoenix library have much larger functionality - For complex lambda expressions, native C++ lambdas are more "future-proof" than boost::lambda2 expressions because you have the full range of the language available. - Having to write using-declarations for each operator in each scope that they are intended to be used defeats the purpose. In the end, the pros outweighed the cons. There was also the concern that boost::lambda2 does not and cannot do short-circuiting of the && and || operators. I suggest writing a rationale and make it clear in the documentation. I think this is a major flaw. But the most glaring issue has to do with ADL: That Boost.Lambda2 defines the operators that should belong to namespace std::placeholders. Hence, the condition that Lambda2 provides its own placeholders instead of importing the standard ones. There were also a couple of suggested improvements. I'll leave that up to Peter to decide whether to implement or not, since these suggestions are not conditions for acceptance. Again, thank you very much everyone, and thank you Peter for submitting this splendid library. Regards, -- Joel
On Thu, 8 Apr 2021 at 07:12, Joel de Guzman via Boost
Hello Y'all,
Thank you all who participated in the review of Lambda2 and thank you Peter for submitting the library.
Boost.Lambda2 is now officially accepted into Boost.
Thank you Joel for managing the review and congratulations to Peter. I've updated the review schedule. Best regards, -- Mateusz Loskot, http://mateusz.loskot.net
Joel de Guzman wrote:
Hello Y'all,
Thank you all who participated in the review of Lambda2 and thank you Peter for submitting the library.
Boost.Lambda2 is now officially accepted into Boost.
... Thank you Joel for managing the review, and thanks to everyone who participated. I will be implementing the review suggestions (own placeholders, more operators) shortly.
Edward Diener wrote:
I also could not decipher what in the world "All operators defined in the subsequent sections only participate in overload resolution if at least one of their operands is such that for its unqualified type T, the expression std::is_placeholder<T>::value || std::is_bind_expression<T>::value is true" means in practical terms. I I see no 'T' s in the subsequent sections, and am just confused.
This just says "at least one of the operands must be a bind expression or a placeholder." `T` in the above is the unqualified type of the operand.
On 22.03.21 03:35, Joel de Guzman via Boost wrote:
The Boost formal review of the Lambda2, authored by Peter Dimov, starts Monday, March 22, 2021 to March 31, 2021 (inclusive).
Documentation: https://pdimov.github.io/lambda2/doc/html/lambda2.html Source: https://github.com/pdimov/lambda2/
So here's my first impression. It's simple, clean, and elegant. However, it doesn't appear to solve any problem I have. In a world where C++ already has "real" lambda expressions as a language feature, is there any need for another lambda library? I assume that the appeal of lambda2 is that it involves less typing. Instead of this: [](char c) { return c == '\n'; } I can type this: _1 == '\n' Fair enough. The latter is clearly shorter, and arguably more readable, than the former. However, there are a lot of extra costs associated with the latter: - I need to put "using namespace boost::lambda2" in my function (or at namespace scope, but I try to avoid "using namespace" at namespace scope where possible). - I (and everybody who reads my code) need to be aware of boost::lambda2. - For complex lambda expressions, C++ lambdas are more "future-proof" than boost::lambda2 expressions because I have the full range of the language available. - In C++ lambdas, operators && and || perform short-circuiting just like in regular C++ code. In boost::lambda2, they do not and cannot. This is another gotcha to keep in mind when using boost::lambda2. I use C++ lambdas fairly often. A small but significant portion of these could be replaced by boost::lambda2 expressions. I am not convinced that doing so would be an improvement. -- Rainer Deyke (rainerd@eldwood.com)
Rainer Deyke wrote:
So here's my first impression. It's simple, clean, and elegant. However, it doesn't appear to solve any problem I have. In a world where C++ already has "real" lambda expressions as a language feature, is there any need for another lambda library?
I assume that the appeal of lambda2 is that it involves less typing.
My impression is similar. I've just gone through my current codebase looking for lambdas that I could re-write using this syntax. Most can't, even the short ones, because I invoke functions or access members, and fn(_1) and _1.field aren't possible. Even when the placeholder form is possible, I lose my meaningful parameter names and possibly types. Pre-C++11 I used to have code that used boost::lambda or similar, but I converted it all to use core language lambdas years ago. I guess that if there are people who still have code using boost::lambda, they may find that they can use lambda2 as a near drop-in replacement and maybe get faster compilation, or something. But I would suggest that they should grasp the nettle and update to just use core-language lambdas. Are there any cases where converting an old boost::lambda expression to a core-language lambda is particularly problematic? Regards, Phil.
Hi
I did some tests with lambda2 some time ago and the review release seems to be the same. One of the useful things in the old lambda is this example:
for_each(a.begin(), a.end(), std::cout << _1 << ' ');
I could not get this to work with lambda2. I am not in a position to run my tests again at the moment. It would be good if this example did work.
John Fletcher
________________________________
From: Boost
Fletcher, John P wrote:
Hi
I did some tests with lambda2 some time ago and the review release seems to be the same. One of the useful things in the old lambda is this example:
for_each(a.begin(), a.end(), std::cout << _1 << ' ');
I could not get this to work with lambda2. I am not in a position to run my tests again at the moment. It would be good if this example did work.
Despite being deceptively simple, this is actually a pretty thorny example for lambda libraries. First off, Lambda2 doesn't even support operator<<, because there's no such function object in <functional>, but let's suppose we fix that. Then, there are two additional obstacles. First, std::cout needs to be taken by reference, but lambda libraries traditionally default to capture by value, and by-ref captures need to be marked with std::ref (or boost::ref). Boost.Lambda gets around that by hardcoding std::ostream& to be taken by reference by default. Second, std::endl is a function template, so template argument deduction of the second operator<< fails against it. Boost.Lambda fails on this one: https://godbolt.org/z/Ec4MYhG56 Boost.Phoenix works as-is, probably by special-casing the stream manipulators: https://godbolt.org/z/5z6vc3bT9 It'd be easy to make the version std::ref(std::cout) << _1 << '\n' work with Lambda2, but the example as-is requires more substantial changes.
Boost.Phoenix works as-is, probably by special-casing the stream manipulators: https://godbolt.org/z/5z6vc3bT9
https://github.com/boostorg/phoenix/blob/master/include/boost/phoenix/operat... Which incidentally leads to amusing results with std::wcout: https://godbolt.org/z/oT35sTM1r :-)
Fletcher, John P wrote:
Hi
I did some tests with lambda2 some time ago and the review release seems to be the same. One of the useful things in the old lambda is this example:
for_each(a.begin(), a.end(), std::cout << _1 << ' ');
I could not get this to work with lambda2. I am not in a position to run my tests again at the moment. It would be good if this example did work.
Despite being deceptively simple, this is actually a pretty thorny example for lambda libraries.
Looks like I mentally replaced ' ' with std::endl in the above, sorry. :-)
My review.
- What is your evaluation of the design?
Extremely simple, solving a very narrow use case.
- What is your evaluation of the implementation?
Unimpeachable. There isn't much to get wrong in 79 lines of code.
- What is your evaluation of the documentation?
Describes the capabilities of the library perfectly clearly.
- What is your evaluation of the potential usefulness of the library?
Since c++14, I have not seen a use case for any library implementations of
lambdas or std::bind at all.
- Did you try to use the library? With which compiler(s)? Did you
have any problems?
Yes, gcc. No issues.
- How much effort did you put into your evaluation? A glance? A quick
reading? In-depth study?
I ignored the simple use cases in the documentation and decided to see if I
could make the library do something more interesting. See below.
- Are you knowledgeable about the problem domain?
Yes
Analysis:
To begin with I wrote a simple function involving c++ lambdas that did not
do arithmetic:
int main1() {
auto source = std::vector{"the"s, "cat"s, "sat"s, "on"s, "the"s, "mat"s};
auto dest = decltype(source)(source.size());
std::transform(source.begin(), source.end(), dest.begin(), [](auto _1) {
for (auto &c : _1)
c = static_cast<char>(std::toupper(static_cast<unsigned char>(c)));
return _1;
});
std::for_each(dest.begin(), dest.end(), [sep = ""](auto &&x) mutable {
std::cout << sep << x;
sep = ", ";
});
std::cout << std::endl;
return 0;
}
The salient part is the transform, but I will comment on the printing of
the result later.
I wondered whether it would be possible to express this transform in terms
of boost::lambda2.
What I really wanted to be able to write was this:
std::transform(source.begin(), source.end(), dest.begin(), uppercase(_1));
However, this is not possible since lambda2 leverages only
arithmetic operators.
So I settled on this:
std::transform(source.begin(), source.end(), dest.begin(), uppercase < _1);
Then I added some boilerplate, which I was able to implement in terms of
lambda2:
constexpr struct uppercase_t {
} uppercase;
template <class C>
concept character =
std::is_same_v
The Boost formal review of the Lambda2, authored by Peter Dimov, starts Monday, March 22, 2021 to March 31, 2021 (inclusive).
Documentation: https://pdimov.github.io/lambda2/doc/html/lambda2.html Source: https://github.com/pdimov/lambda2/
Lambda2 is a simple, but functional, C++14 lambda library. It takes advantage of the fact that the standard <functional> header already provides placeholders _1, _2, _3, and so on, for use with std::bind, and function objects such as std::plus, std::greater, std::logical_not, and std::bit_xor, corresponding to arithmetic, relational, logical and bitwise operators.
Please provide in your review information you think is valuable to understand your choice to ACCEPT or REJECT including Lambda2 as a Boost library. Please be explicit about your decision (ACCEPT or REJECT).
Some other questions you might want to consider answering:
- What is your evaluation of the design? - What is your evaluation of the implementation? - What is your evaluation of the documentation? - What is your evaluation of the potential usefulness of the library? - Did you try to use the library? With which compiler(s)? Did you have any problems? - How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? - Are you knowledgeable about the problem domain?
More information about the Boost Formal Review Process can be found at: http://www.boost.org/community/reviews.html
The review is open to anyone who is prepared to put in the work of evaluating and reviewing the library. Prior experience in contributing to Boost reviews is not a requirement.
Thank you for your efforts in the Boost community. They are very much appreciated.
Peter is often available in the CppLang Slack #boost channel should you require any clarification not covered by the documentation. I am not frequently available in the Slack channel, but I'll certainly pay attention to the discussions. Please don't hesitate to ping me if needed.
Cheers, --Joel de Guzman
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Richard Hodges wrote:
So I settled on this:
std::transform(source.begin(), source.end(), dest.begin(), uppercase < _1);
:-) FWIW, the "idiomatic" way is to use `std::bind( uppercase, _1 )`, although in this specific case this can be shortened to just `uppercase`.
At this point I was presented with a dilemma. On the one hand, the library is concise, correct, limited in scope and well documented. On the other, it doesn't do anything other than remove a few keystrokes in the rare case that I want a lambda to do some adding up or taking away.
That's basically what it's about for new code, removing a few keystrokes (if we discount the use cases related to porting existing Boost.Bind or Boost.Lambda code to C++14.) The motivation comes from the various "abbreviated lambda" proposals, which aim to provide an alternative, more concise, syntax for core language lambdas. There's a good blog post by Barry Revzin about the verbosity of C++ lambdas compared to other languages: https://brevzin.github.io/c++/2020/06/18/lambda-lambda-lambda/ The goal here is to make simple lambdas shorter, not to compete with the core language lambdas in all cases, which is neither possible nor necessary. If you just need to say _1 < 0, or _1 < x, or _1 * 2 + 1, the language lambda boilerplate takes up more than 50% of the whole thing. If, on the other hand, you need to express something more complex than Lambda2 can handle, switch to the language lambda.
On Wed, 24 Mar 2021 at 17:57, Peter Dimov via Boost
The goal here is to make simple lambdas shorter, not to compete with the core language lambdas in all cases, which is neither possible nor necessary.
If you just need to say _1 < 0, or _1 < x, or _1 * 2 + 1, the language lambda boilerplate takes up more than 50% of the whole thing. If, on the other hand, you need to express something more complex than Lambda2 can handle, switch to the language lambda.
Thanks for the explanation. my vote is to ACCEPT
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
On Wed, 24 Mar 2021 at 17:57, Peter Dimov via Boost
wrote: The goal here is to make simple lambdas shorter, not to compete with the core language lambdas in all cases, which is neither possible nor necessary.
If you just need to say _1 < 0, or _1 < x, or _1 * 2 + 1, the language lambda boilerplate takes up more than 50% of the whole thing. If, on the other hand, you need to express something more complex than Lambda2 can handle, switch to the language lambda.
Why not add some nice syntactic sugar to the shipping library, i.e. something like this:
template< typename A, typename F> int operator+= (A&& a, F&& f) {return std::count_if( a.cbegin(), a.cend(), f);}
template
Le lundi 22 mars 2021 à 10:35 +0800, Joel de Guzman via Boost a écrit :
The Boost formal review of the Lambda2, authored by Peter Dimov, starts Monday, March 22, 2021 to March 31, 2021 (inclusive).
Here's my small review of the lambda 2 library. TLDR: ACCEPT
- What is your evaluation of the design? - What is your evaluation of the implementation?
The library is a really small piece of code, like other reviewers already noticed. During my tests, i came across two things that could be improved: * the internal macro BOOST_LAMBDA2_UNARY_LAMBDA and BOOST_LAMBDA2_BINARY_LAMBDA #undefed at the end of the file. While i undestand that it is an internal macro, it could be exposed to the user to allow implementation for other operators * that macro hardcode the std prefix, it could be part of its call, ie: BOOST_LAMBDA2_BINARY_LAMBDA(+, std::plus) // instead of BOOST_LAMBDA2_BINARY_LAMBDA(+, plus) This would allow the user of the library to get the building blocks to customize other operators to its needs (I have implemented unary operator* easily that way).
- What is your evaluation of the documentation?
The documentation is really good at telling what the library does, is clean, nice looking.
- What is your evaluation of the potential usefulness of the library?
At first glance, i was thinking that this was the kind of library that
i would never use. I find the count_if examples in the documentation
not really convincing.
Then, it happened that i made some experiments with c++20 ranges. And i
find that, in this context, shortening the lambdas gives a real benefit
to the code. It basically started from the need to feed a function that
was needing a list of non owner references to T from a
vector
- Did you try to use the library? With which compiler(s)? Did you have any problems?
No specific issue encountered, with gcc-10. Error messages are a bit cryptic.
- How much effort did you put into your evaluation? A glance? A quick reading? In-depth study?
A few hours playing with the library.
- Are you knowledgeable about the problem domain?
Not at all. My feeling is the following. At first glance, i was wondering what was the use case the library addressed. After playing a bit with it, i'm now convinced that people will want to use it, and, like me, will probably want to expand it to fit their need. I was not suspecting that it was possible to write code that way. I suspect most developers are not either. Now that it is known it's possible, people will come up with their own, probably inferior, solution. Having such a feature in boost would at least provide everyone with a correct implementation of it. Because people will want to write code like this, and i believe, especially with ranges. Thanks to Peter for writing this library, and proposing it to boost. Reviewing it has been very interesting and instructive. Regards, Julien
czw., 25 mar 2021 o 19:11 Julien Blanc via Boost
Le lundi 22 mars 2021 à 10:35 +0800, Joel de Guzman via Boost a écrit :
The Boost formal review of the Lambda2, authored by Peter Dimov, starts Monday, March 22, 2021 to March 31, 2021 (inclusive).
Here's my small review of the lambda 2 library.
TLDR: ACCEPT
- What is your evaluation of the design? - What is your evaluation of the implementation?
The library is a really small piece of code, like other reviewers already noticed. During my tests, i came across two things that could be improved: * the internal macro BOOST_LAMBDA2_UNARY_LAMBDA and BOOST_LAMBDA2_BINARY_LAMBDA #undefed at the end of the file. While i undestand that it is an internal macro, it could be exposed to the user to allow implementation for other operators * that macro hardcode the std prefix, it could be part of its call, ie:
BOOST_LAMBDA2_BINARY_LAMBDA(+, std::plus) // instead of BOOST_LAMBDA2_BINARY_LAMBDA(+, plus)
This would allow the user of the library to get the building blocks to customize other operators to its needs (I have implemented unary operator* easily that way).
Is it not just that the library is missing some operators? If Boost.Lambda2 overloaded all overloadable operators there would be no point in users doing it.
- What is your evaluation of the documentation?
The documentation is really good at telling what the library does, is clean, nice looking.
- What is your evaluation of the potential usefulness of the library?
At first glance, i was thinking that this was the kind of library that i would never use. I find the count_if examples in the documentation not really convincing.
Then, it happened that i made some experiments with c++20 ranges. And i find that, in this context, shortening the lambdas gives a real benefit to the code. It basically started from the need to feed a function that was needing a list of non owner references to T from a vector
. As I was not satisfied with the solution, I checked whether c++20 ranges could provide an elegant solution to this. Something like f(std::views::transform(vec, deref));
implementing deref is easy. Then, out of curiosity, i checked if i could use Peter's library to be able to write something like:
f(std::views::transform(vec, *_1));
I actually find that this way of writing is more natural than the former.
This is an interesting observation. In my experience, storing collections of ints is a rare case in production code (it is frequent in tests, tutorials, books, presentations), maybe this is why arithmetic operators do not appear as something practical. However pointers (including smart ones) to user-defined types is something that I see a lot. The following als looks as something I would see often in the code: assert(std::ranges::all_of(records, _1 != nullptr)); Regards, &rzej;
So, i wrote :
namespace std // BAD, don't do that { template<typename T = void> struct deref { decltype(auto) operator()(T& v) { return *v; } }; template<> struct deref<void> { template<typename T> decltype(auto) operator()(T& v) { return *v; } }; }
BOOST_LAMBDA2_UNARY_LAMBDA(*, deref);
modified Peter's library to remove the #undef, and voila, it just works.
I see a lot of potential for the short writing form for lambdas, in conjunction with the ranges library. I find convenient to write:
f(std::views::transform(vec, _1 + 1)) // convert from 0-based to 1- based index
- Did you try to use the library? With which compiler(s)? Did you have any problems?
No specific issue encountered, with gcc-10. Error messages are a bit cryptic.
- How much effort did you put into your evaluation? A glance? A quick reading? In-depth study?
A few hours playing with the library.
- Are you knowledgeable about the problem domain?
Not at all.
My feeling is the following. At first glance, i was wondering what was the use case the library addressed. After playing a bit with it, i'm now convinced that people will want to use it, and, like me, will probably want to expand it to fit their need. I was not suspecting that it was possible to write code that way. I suspect most developers are not either. Now that it is known it's possible, people will come up with their own, probably inferior, solution. Having such a feature in boost would at least provide everyone with a correct implementation of it. Because people will want to write code like this, and i believe, especially with ranges.
Thanks to Peter for writing this library, and proposing it to boost. Reviewing it has been very interesting and instructive.
Regards,
Julien
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Le vendredi 26 mars 2021 à 05:54 +0100, Andrzej Krzemienski via Boost a écrit :
This would allow the user of the library to get the building blocks to customize other operators to its needs (I have implemented unary operator* easily that way).
Is it not just that the library is missing some operators? If Boost.Lambda2 overloaded all overloadable operators there would be no point in users doing it.
Agreed. But I don't have a strong opinion on whether the library should implement everything, or just be more open to user extensions.
The following als looks as something I would see often in the code:
assert(std::ranges::all_of(records, _1 != nullptr));
Definitely. That's the kind of motivating example that i think should appear in the documentation. Regards, Julien
On Fri, 26 Mar 2021 at 04:54, Andrzej Krzemienski via Boost
This is an interesting observation. In my experience, storing collections of ints is a rare case in production code (it is frequent in tests, tutorials, books, presentations), maybe this is why arithmetic operators do not appear as something practical.
They do appear frequently if you use column-oriented data structures, which are generally better at dealing with large collections of data.
Andrzej Krzemienski wrote:
Is it not just that the library is missing some operators? If Boost.Lambda2 overloaded all overloadable operators there would be no point in users doing it.
I'll add the shift operators and the unary * at minimum, will see about any others. The current set is determined by the function objects in <functional>.
Hey everyone, I vote to *ACCEPT *Lambda2. I first heard of Lambda2 when Peter asked me how many lines I thought it would take to recreate Boost.Lambda. Naturally, I should've seen this as a loaded question but I guessed a few hundred. Maybe something just below a couple thousand by the time all the dust settles. Peter told me it could be done in ~50 lines. Now I was intrigued. The source code of Lambda2 is wonderfully clever and short. Moreso, sufficiently clever that it's worth not repeating every time we want to use it. Higher-order functions are all the rage in C++ and writing lambdas is cumbersome and annoying. Lambda2 gives us a C++14 solution that relies on nothing else but simple language features and stdlib headers making it faster to compile than older solutions such as Phoenix or the original Lambda. Lambda2 also has the fortune of interop'ing greatly with existing constructs like Boost.HOF and the new `<ranges>` STL header. See: https://godbolt.org/z/hfxfhfEqv Keeping this short, Lambda2 gives us fresh paint over an old technology that we know works and one that (while polarizing in its style) does its job well. I think it ultimately serves Boost and the larger C++ community to keep this Lambda-style of coding alive and well-maintained as C++ evolves. - Christian
On Mon, 22 Mar 2021 at 02:35, Joel de Guzman via Boost
The Boost formal review of the Lambda2, authored by Peter Dimov, starts Monday, March 22, 2021 to March 31, 2021 (inclusive).
Documentation: https://pdimov.github.io/lambda2/doc/html/lambda2.html Source: https://github.com/pdimov/lambda2/
Lambda2 is a simple, but functional, C++14 lambda library. It takes advantage of the fact that the standard <functional> header already provides placeholders _1, _2, _3, and so on, for use with std::bind, and function objects such as std::plus, std::greater, std::logical_not, and std::bit_xor, corresponding to arithmetic, relational, logical and bitwise operators.
Please provide in your review information you think is valuable to understand your choice to ACCEPT or REJECT including Lambda2 as a Boost library. Please be explicit about your decision (ACCEPT or REJECT).
Some other questions you might want to consider answering:
- What is your evaluation of the design? - What is your evaluation of the implementation? - What is your evaluation of the documentation?
It is not clear from the documentation what the capture behaviour of terminals is. I assume it's capturing rvalues by value and lvalues by reference? What about the expression tree itself, is it fully by value, and therefore safely copyable? Boost.Proto for example by default is binding everything by reference, meaning that you couldn't even store the expression in a variable. Is it avoiding this issue?
Mathias Gaunard wrote:
It is not clear from the documentation what the capture behaviour of terminals is. I assume it's capturing rvalues by value and lvalues by reference?
The capture behavior is inherited from std::bind, which captures everything by value by default unless overridden with std::ref.
Here is my review of lambda2: I remember when I first learned boost::bind, and realized how much more useful STL is because of it. Even after C++11 I still find myself using bind, it sometimes looks more readable to my eyes than a lambda. The lambda2 library is one more proof for the solid design behind std::bind. That, or std::bind was designed with things like lambda2 in mind. Either way, lambda2 is an elegant utility for writing elegant C++, albeit only in the (rare?) cases when it is a perfect fit. Given this, and the miniature size of the library, my vote is to ACCEPT.
On 3/22/21 10:35 am, Joel de Guzman wrote:
The Boost formal review of the Lambda2, authored by Peter Dimov, starts Monday, March 22, 2021 to March 31, 2021 (inclusive).
Documentation: https://pdimov.github.io/lambda2/doc/html/lambda2.html Source: https://github.com/pdimov/lambda2/
Reminder: the review period of Lambda2 ends March 31, 2021. Please send in your review if you haven't done so yet. Thank you! Regards -- Joel de Guzman
participants (17)
-
Andrzej Krzemienski
-
Christian Mazakas
-
Edward Diener
-
Emil Dotchevski
-
Fletcher, John P
-
Gavin Lambert
-
Jeff Flinn
-
Joel de Guzman
-
Julien Blanc
-
Kostas Savvidis
-
Mateusz Loskot
-
Mathias Gaunard
-
Peter Dimov
-
Phil Endecott
-
Rainer Deyke
-
Richard Hodges
-
Robert Ramey