[Fit] Formal review / Kris
Hi, Firstly, sorry for submitting my review so late.
- Whether you believe the library should be accepted into Boost
Yes. Although the submission is not perfect, I prefer boolean logic, and, therefore Fit a 1 for me.
- Your name
Krzysztof Jusiak
- Your knowledge of the problem domain.
I have been implementing similar solutions myself when experimenting with lambdas. I have also checked out functional part of Hana library.
You are strongly encouraged to also provide additional information: - What is your evaluation of the library's: * Design
IMHO design is decent. Functionality is loosely coupled and really easy to follow. There are a few inconsistencies here and there but there were pointed out already and they don't have a huge impact on the overall solution.
* Implementation
Quite a lot of macros but most of these are due to lack of language features or compilers bugs. Besides that, it looks alright. Moreover, I do agree with most issues pointed out already.
* Documentation
Motivation could have been much better. Examples showing how much pain might be saved using Fit in comparison to writing the same things by hand would be great. Moreover, ready to copy examples would simplify testing the library. Personally, I would also add disassembled code for these examples showing how well-optimized code Fit can produce. Maybe, it's worth to add try-it-online functionality too?
* Tests
Tests are short and easy to follow. I can't see coverage but it seems like most things are tested. Travis addition with each push make me confident that the library is always in a good shape. I would like to see performance tests though for both compilation times and run times.
* Usefulness
IMHO Fit is defo a library to have in Boost for modern C++ development. I find the solutions provided by Fit very useful as I have been writing similar functionality myself. Nevertheless, documentation needs improving (as it was stated already) in order to state the purpose more clearly with clean examples. I have been worrying that there will be a clash with Hana. Having 2 modern libraries providing similar functionality would be confusing, however, my concerns were already clarified by Louis.
- Did you attempt to use the library? If so: * Which compiler(s)
Clang 3.7/3.8/HEAD, MSVC 2015
* What was the experience? Any problems?
No issues.
- How much effort did you put into your evaluation of the review?
A few hours for the review, however, I have been looking and trying Fit for a while. Cheers, Kris
On Saturday, March 19, 2016 2:26 PM, Krzysztof Jusiak
wrote: Hi,
Firstly, sorry for submitting my review so late.
- Whether you believe the library should be accepted into Boost
Yes. Although the submission is not perfect, I prefer boolean logic, and, therefore Fit a 1 for me.
- Your name
Krzysztof Jusiak
- Your knowledge of the problem domain.
I have been implementing similar solutions myself when experimenting with lambdas. I have also checked out functional part of Hana library.
You are strongly encouraged to also provide additional information: - What is your evaluation of the library's: * Design
IMHO design is decent. Functionality is loosely coupled and really easy to follow. There are a few inconsistencies here and there but there were pointed out already and they don't have a huge impact on the overall solution.
* Implementation
Quite a lot of macros but most of these are due to lack of language features or compilers bugs. Besides that, it looks alright. Moreover, I do agree with most issues pointed out already.
* Documentation
Motivation could have been much better. Examples showing how much pain might be saved using Fit in comparison to writing the same things by hand would be great. Moreover, ready to copy examples would simplify testing the library. Personally, I would also add disassembled code for these examples showing how well-optimized code Fit can produce. Maybe, it's worth to add try-it-online
functionality too?
Thats a good idea. I'll try show some disassembly to show how well the optimizer does. I like the idea of having a try-it-online, however, I would like a way to better handle versioning and offline documentation. I am sure there is a nice solution to this I just haven't time to figure it out yet.
* Tests
Tests are short and easy to follow. I can't see coverage but it seems like most things are tested. Travis addition with each push make me confident that the library is always in a good shape. I would like to see performance tests though for both compilation times and
run times.
Yes, I have run a couple of local tests to test performance. I could pull together some report to put in the documentation. Ideally. it would be good to have a comparison with other libraries as well. I haven't compared it with Hana yet, either, which would be a good idea. However, I do know that the implementation of `fit::conditional` is much faster than the implemenation used for `overload_linearly` in Hana, but I haven't done a direct comparison. I'll try to add something like that. I think it will be useful.
* Usefulness
IMHO Fit is defo a library to have in Boost for modern C++ development. I find the solutions provided by Fit very useful as I have been writing similar functionality myself. Nevertheless, documentation needs improving (as it was stated already) in order to state the purpose more clearly with clean examples. I have been worrying that there will be a clash with Hana. Having 2 modern libraries providing similar functionality would be confusing, however, my concerns were already clarified by Louis.
- Did you attempt to use the library? If so: * Which compiler(s)
Clang 3.7/3.8/HEAD, MSVC 2015
* What was the experience? Any problems?
No issues.
- How much effort did you put into your evaluation of the review?
A few hours for the review, however, I have been looking and trying
Fit for a while.
Thanks Kris for the review and feedback.
Cheers, Kris
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Paul Fultz II wrote
[...]
Yes, I have run a couple of local tests to test performance. I could pull together some report to put in the documentation. Ideally. it would be good to have a comparison with other libraries as well. I haven't compared it with Hana yet, either, which would be a good idea. However, I do know that the implementation of `fit::conditional` is much faster than the implemenation used for `overload_linearly` in Hana, but I haven't done a direct comparison. I'll try to add something like that. I think it will be useful.
How so? The implementations are very similar, except Hana also allows for non-const function objects. I'd be grateful if you could provide a benchmark, perhaps I could improve Hana's implementation. Regards, Louis -- View this message in context: http://boost.2283326.n4.nabble.com/Fit-Formal-review-Kris-tp4684694p4684731.... Sent from the Boost - Dev mailing list archive at Nabble.com.
On Sunday, March 20, 2016 at 10:44:45 AM UTC-5, Louis Dionne wrote:
[...]
Yes, I have run a couple of local tests to test performance. I could
together some report to put in the documentation. Ideally. it would be good to have a comparison with other libraries as well. I haven't compared it with Hana yet, either, which would be a good idea. However, I do know that
Paul Fultz II wrote pull the
implementation of `fit::conditional` is much faster than the implemenation used for `overload_linearly` in Hana, but I haven't done a direct comparison. I'll try to add something like that. I think it will be useful.
How so? The implementations are very similar, except Hana also allows for non-const function objects. I'd be grateful if you could provide a benchmark, perhaps I could improve Hana's implementation.
Actually looking at your implementation closer, I realized thats not the case. I originally had an implementation where I ranked the overloads, and your implementation looked similar to that when using `which`. However, after looking at it closer, it won't ever instantiate the second function if the first function is callable. Sorry for the confusion. However, one notable difference though is that fit::conditional is SFINAE- friendly, which makes it very composable. So in Fit, one can write `fit::conditional(fit::conditional(f, g), h)` and it will work as the equivalent of `fit::conditional(f, g, h)`. However, in Hana, `hana::overload_linearly(hana::overload_linearly(f, g), h)` works as the equivalent of `hana::overload_linearly(f, g)`(note the missing h). Of course, this more of a philosophical difference between Fit and Hana, as Hana lacks SFINAE-friendliness throughout the entire library and uses its own mechanism to compose failures. I don't think the Fit library is incompatible with that mechanism.
Regards, Louis
-- View this message in context: http://boost.2283326.n4.nabble.com/Fit-Formal-review-Kris-tp4684694p4684731.... Sent from the Boost - Dev mailing list archive at Nabble.com.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Paul Fultz II wrote
On Sunday, March 20, 2016 at 10:44:45 AM UTC-5, Louis Dionne wrote:
[...] How so? The implementations are very similar, except Hana also allows for non-const function objects. I'd be grateful if you could provide a benchmark, perhaps I could improve Hana's implementation.
Actually looking at your implementation closer, I realized thats not the case. I originally had an implementation where I ranked the overloads, and your implementation looked similar to that when using `which`. However, after looking at it closer, it won't ever instantiate the second function if the first function is callable. Sorry for the confusion.
I'm not sure I understand what you mean. I mean, it is expected that the function is never called when the first one could be called, since it's overload _linearly_, right? Louis -- View this message in context: http://boost.2283326.n4.nabble.com/Fit-Formal-review-Kris-tp4684694p4684766.... Sent from the Boost - Dev mailing list archive at Nabble.com.
On Monday, March 21, 2016 at 8:34:16 AM UTC-5, Louis Dionne wrote:
On Sunday, March 20, 2016 at 10:44:45 AM UTC-5, Louis Dionne wrote:
[...] How so? The implementations are very similar, except Hana also allows for non-const function objects. I'd be grateful if you could provide a benchmark, perhaps I could improve Hana's implementation.
Actually looking at your implementation closer, I realized thats not the case. I originally had an implementation where I ranked the overloads, and your implementation looked similar to that when using `which`. However, after looking at it closer, it won't ever instantiate the second function if
Paul Fultz II wrote the
first function is callable. Sorry for the confusion.
I'm not sure I understand what you mean. I mean, it is expected that the function is never called when the first one could be called, since it's overload _linearly_, right?
Yes, but another way to achieve that is to use a ranked tag-dispatching.
Like
this:
template<int N>
struct rank : rank<N-1>
{};
template<>
struct rank<0>
{};
// Call F
template
Louis
-- View this message in context: http://boost.2283326.n4.nabble.com/Fit-Formal-review-Kris-tp4684694p4684766.... Sent from the Boost - Dev mailing list archive at Nabble.com.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Paul Fultz II wrote
On Monday, March 21, 2016 at 8:34:16 AM UTC-5, Louis Dionne wrote:
[...]
I'm not sure I understand what you mean. I mean, it is expected that the function is never called when the first one could be called, since it's overload _linearly_, right?
Yes, but another way to achieve that is to use a ranked tag-dispatching. Like this:
template <int N> struct rank : rank <N-1> {};
template<> struct rank<0> {};
// Call F template
auto foo_impl(Ts&&... xs, rank<1>) -> decltype(std::declval <F> ()(std::forward <Ts> (xs)...)); // Call G template
auto foo_impl(Ts&&... xs, rank<0>) -> decltype(std::declval <G> ()(std::forward <Ts> (xs)...)); template
auto foo_impl(Ts&&... xs) -> decltype(foo_impl(std::forward <Ts> (xs)..., rank<1>{})); So `G` will not be called if `F` is callable, however, the compiler will instantiate both `F` and `G` with this implementation. I used to use an implementation like this, but it is more costly at compile time. Furthermore, lazy instantiation is nice feature as well, especially when using constexpr, as the body of a constexpr function is always instantiated during substitution.
I'm very surprised to learn that the compiler will instantiate both F and G in the code you posted above. Can't the compiler determine that the first `foo_impl` should be chosen if `decltype(std::declval<F>()(...))`does not SFINAE out because rank<1> is a better match than rank<0>, and this without ever looking at `std::declval<G>()(...)`? Anyway, IIUC, `hana::overload_linearly` has this problem, so I'll change it. Thanks for the heads up. Louis -- View this message in context: http://boost.2283326.n4.nabble.com/Fit-Formal-review-Kris-tp4684694p4684785.... Sent from the Boost - Dev mailing list archive at Nabble.com.
On Monday, March 21, 2016 at 4:30:16 PM UTC-5, Louis Dionne wrote:
Paul Fultz II wrote
On Monday, March 21, 2016 at 8:34:16 AM UTC-5, Louis Dionne wrote:
[...]
I'm not sure I understand what you mean. I mean, it is expected that the function is never called when the first one could be called, since it's overload _linearly_, right?
Yes, but another way to achieve that is to use a ranked tag-dispatching. Like this:
template <int N> struct rank : rank <N-1> {};
template<> struct rank<0> {};
// Call F template
auto foo_impl(Ts&&... xs, rank<1>) -> decltype(std::declval <F> ()(std::forward <Ts> (xs)...)); // Call G template
auto foo_impl(Ts&&... xs, rank<0>) -> decltype(std::declval <G> ()(std::forward <Ts> (xs)...)); template
auto foo_impl(Ts&&... xs) -> decltype(foo_impl(std::forward <Ts> (xs)..., rank<1>{})); So `G` will not be called if `F` is callable, however, the compiler will instantiate both `F` and `G` with this implementation. I used to use an implementation like this, but it is more costly at compile time. Furthermore, lazy instantiation is nice feature as well, especially when using constexpr, as the body of a constexpr function is always instantiated during substitution.
I'm very surprised to learn that the compiler will instantiate both F and G in the code you posted above. Can't the compiler determine that the first `foo_impl` should be chosen if `decltype(std::declval<F>()(...))`does not SFINAE out because rank<1> is a better match than rank<0>, and this without ever looking at `std::declval<G>()(...)`?
I would think it would more complicated for the compiler to build a structure to know that.
Anyway, IIUC, `hana::overload_linearly` has this problem, so I'll change it. Thanks for the heads up.
After looking at it closer, I don't think Hana has that problem, because you
never invoke the second function when the function is picked. You do
something
like this instead:
template<int N>
struct rank : rank<N-1>
{};
template<>
struct rank<0>
{};
// pick F
template
Louis
-- View this message in context: http://boost.2283326.n4.nabble.com/Fit-Formal-review-Kris-tp4684694p4684785.... Sent from the Boost - Dev mailing list archive at Nabble.com.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Paul Fultz II wrote
On Monday, March 21, 2016 at 4:30:16 PM UTC-5, Louis Dionne wrote:
[...]
Anyway, IIUC, `hana::overload_linearly` has this problem, so I'll change it. Thanks for the heads up.
After looking at it closer, I don't think Hana has that problem, because you never invoke the second function when the function is picked. You do something like this instead:
[...]
Oh yeah, you're right. Now I'm the one that's sorry for the confusion. Ok, so all's good then. Louis -- View this message in context: http://boost.2283326.n4.nabble.com/Fit-Formal-review-Kris-tp4684694p4684815.... Sent from the Boost - Dev mailing list archive at Nabble.com.
participants (4)
-
Krzysztof Jusiak
-
Louis Dionne
-
paul Fultz
-
Paul Fultz II