Hi, Please find my review below. - Whether you believe the library should be accepted into Boost Definitely YES. IMHO, one of the most complete boost proposals. - Your name Krzysztof Jusiak - Your knowledge of the problem domain. I've been using MPL and Fusion for about 6 years in commercial projects, I also have been using C++11 /C++14 template features in open source projects since they become available. I have some experience with Haskell and other functional programming languages. You are strongly encouraged to also provide additional information: - What is your evaluation of the library's: * Design Library seems to be very well designed. Used patterns are easy to follow. There is a distinction between algorithms, data types and concepts. The approach is really easy to follow for Haskell programmers, but, on the other hand, C++ influence might be noticed as well. Seems to be very straight forward mix of approaches. * Implementation Source Code: First impression, it's a lot of it! But it's easy to follow. Helpful directory structure makes it much easier to handle. Big thanks for changing the naming as well, `snoc`, `cons` and so on, could have been hard to follow for C++ programmers. Implementation consist of a high quality source code. There are few small things, which are not as straight forward. * a lot of fwd (assume forward declaration files) files have implementation inside, which is a bit confusing * a bit annoying `#ifdef BOOST_HANA_DOXYGEN_INVOKED` all over the source code Performance: I have to admit, I really appreciate the library handled this topic. MPL/Fusion, although, very useful are really hard to introduce in commercial projects in the large scale. I do remember using Boost.MSM for a bit, but the company had to give up on it, because having a transition table with more than 200 entries wasn't easy to deal with, to say at least. Having sad that, I think Hana can still improve the compilation times. I didn't even bother to compare it to MPL or Fusion, because there is no comparison there, but with C++ template tricks there is. Compilation time: So I have written simple example to compare `Hana Map` and `C++ Tricks Map`. Please notice, I compared map with 1000 entries! Hehehe, can anyone imagine that with MPL or Fusion? Results are here: tricks_map: https://gist.github.com/krzysztof-jusiak/cb6633d6c11572c33928 0m0.095s hana_map: https://gist.github.com/krzysztof-jusiak/949d3916d84c466b80c5 0m11.105s So, Hana seems to be much slower, but still not really slow. It's not hours, just a few seconds, which IMHO, it's a huge improvement already. run-time: Haven't checked this part as deeply. Diagnostic Messages: Really popular topic recently and Hana made a huge progress with it as well. Concepts helps a lot, but, unfortunately, there is always a call stack following the error message. Sometimes, such approach is desired, but would be great not to see all Hana's internals, especially with recursive algorithms. Tested error message: https://gist.github.com/krzysztof-jusiak/bfc51747d083e140772d I also had some issue, when some include was missing. Compilation was fine, but the computation was run-time only. Would be great to somehow handle this problem. It's really tricky to understand, why it doesn't work as expected. Debugging: Guess, in this matter, there is still no much progress. I tried Hana with MetaShell and TempLight, but, although, it was way better experience, it still was hard to debug the library. What about run-time algorithms? I haven't checked how hard it is to debug them, but I suspect it will be the same story as with STL, unless some magic is happening in HANA under the hood? * Documentation Documentation is really impressive. Honestly, love the search button! Would like to see more copy/paste examples tho. I'm really inpatient sometimes and when have to find part of the example at one place and figure out includes I do get easily annoyed. Related to that, would be great to always see which file has to be included for anything which is not included by `boost/hana.hpp`. As already mentioned, would be better to use hana::... instead of having an assumption for `using namespace boost::hana`. I would also add some tutorial for less experienced users with explanations what the monad is and how functional programming concepts are applied in Hana. * Tests Impressive unit tests collection. Unfortunately, they are not that easy to follow. Approach like: // check a { } // check b { } is not the best and I would encourage to add separate tests for both cases. Would be great to have CI tests for run-time performance. I have seen charts, but the build could break when performance degradation occurred. * Usefulness With C++11/C++14/C++17 template metaprogramming become a lot easier and a a lot of stuff might be written without need of TMP library at all. However, Hana is more than that, and I find it very useful. MPL and Fusions are/were extremely helpful and Hana is a huge step forward. *Frankly speaking, I would replace `std::tuple` with `hana::tuple` straight away.* - Did you attempt to use the library? If so: * Which compiler(s) Clang 3.6/Clang 3.7 + libc++ (on linux/mac/windows) -> worked fine Tried on GCC-5.1 (on linux) without any success -> didn't link, but this issue is well known already Tried on MSVC 2015-RC (just for a sake of trying -> didn't work ;) * What was the experience? Any problems? I haven't experienced any blockers whilst trying the library. The only problem for me, is lack of support for MSVC. A lot of commercial projects requires MSVC as much as Clang/GCC. - How much effort did you put into your evaluation of the review? I have been watching/trying Hana since April last year when I started to implement C++14 version of proposed boost.di library. I tried to re-implement C++03 version using Hana, but back then, Hana was crashing very often. Therefore, I decided to use plain C++14 features instead. I also went through all the source code/documentation/examples as well as played with the library. Thanks Louis for a great library! Kris
Krzysztof Jusiak
[...]
Compilation time: So I have written simple example to compare `Hana Map` and `C++ Tricks Map`. Please notice, I compared map with 1000 entries! Hehehe, can anyone imagine that with MPL or Fusion?
For the record, Hana's Map is not optimized right now. This is the subject of my GSoC project for this summer. So the performance should be pretty bad.
Results are here: tricks_map:
https://gist.github.com/krzysztof-jusiak/cb6633d6c11572c33928 0m0.095s
hana_map:
https://gist.github.com/krzysztof-jusiak/949d3916d84c466b80c5 0m11.105s
So, Hana seems to be much slower, but still not really slow. It's not hours, just a few seconds, which IMHO, it's a huge improvement already.
Actually, I think it is very good. Indeed, the current Map implementation is very dumb and lookup is done by doing a linear search inside a tuple. Doing a short-circuiting linear search in a 1k element Tuple without busting the recursion limit is, I think, an achievement by itself. Actually, I have to check why it works :-). Of course, this does not mean that the Map should not be optimized: it will, and I expect to match roughly the performance of a hand-written Map.
run-time: Haven't checked this part as deeply.
Diagnostic Messages: Really popular topic recently and Hana made a huge progress with it as well. Concepts helps a lot, but, unfortunately, there is always a call stack following the error message. Sometimes, such approach is desired, but would be great not to see all Hana's internals, especially with recursive algorithms.
I think this call stack is desirable, since it allows you to see where things blew up. Of course, there are a couple of levels of Hana-stuff in there, but you'll get the exact same thing if you instantiate a STL algorithm with an improper predicate. The only way to reduce the number of in-between steps would be to inline Hana's functions by-hand. I think language support would be needed to get significantly better diagnostics. Also, if you'll notice, there are only two errors here. One is the actual error you made in the code, and the other one refers to a call to some deleted function `apply`. Usually, the compiler would explode and give a truck of error messages because it tries to continue compiling even after the error occurs. However, Hana will disable the next call when an error happens to make these useless messages disappear. That's where the call to a deleted function comes from.
Tested error message:
https://gist.github.com/krzysztof-jusiak/bfc51747d083e140772d
<aside> Ahaha! Finally I get this example I was looking for! To all of those that say "lambdas can't appear in unevaluated contexts because of implementation difficulties", I now dare say "Bullshit"! If you look at the above example, you'll notice that a lambda happily appears inside a `decltype(...)`. This is a Clang glitch (the only one I never reported) that only works in some specific circumstances, which allows us to have lambdas appear inside unevaluated contexts. This allows us to write type-level computations with value syntax inline, without ever needing to create an external variable. I want lambdas in unevaluated contexts for C++17. Please. Also, people, please don't report this bug :-). </aside>
I also had some issue, when some include was missing. Compilation was fine, but the computation was run-time only. Would be great to somehow handle this problem. It's really tricky to understand, why it doesn't work as expected.
Can you share a link to that example? It would be helpful for me to see the exact thing so I can try to find a solution.
Debugging: Guess, in this matter, there is still no much progress. I tried Hana with MetaShell and TempLight, but, although, it was way better experience, it still was hard to debug the library. What about run-time algorithms? I haven't checked how hard it is to debug them, but I suspect it will be the same story as with STL, unless some magic is happening in HANA under the hood?
If your code compiles and you have a runtime bug, you can debug your code with a normal runtime debugger, just like you would do with the STL. You'll have to jump through a lot of function calls however, since heterogeneous algorithms can (in most cases) only be implemented recursively. For debugging something that does not compile, I do not have a proper solution, and I think an external tool is really required. However, since Hana is functional in nature, it is often possible to extract large chunks of code and to just cut/paste stuff around to reduce your problem. Since there's no mutation, it's fairly straightforward. Of course, that is still not very satisfactory, but the problem is with C++.
* Documentation Documentation is really impressive. Honestly, love the search button! Would like to see more copy/paste examples tho. I'm really inpatient sometimes and when have to find part of the example at one place and figure out includes I do get easily annoyed. Related to that, would be great to always see which file has to be included for anything which is not included by `boost/hana.hpp`.
Ok, I will try to make the examples self-contained. See this issue [1].
As already mentioned, would be better to use hana::... instead of having an assumption for `using namespace boost::hana`. I would also add some tutorial for less experienced users with explanations what the monad is and how functional programming concepts are applied in Hana.
I think that explaining Monads is out of scope for Hana. What I can do is provide helpful links to existing tutorials, but I don't want to fall in the Monad Tutorial Fallacy [2]. I do agree that more extensive examples of how the functional concepts can be used in the specific context of metaprogramming would be helpful. I'll try to improve some of the examples given for Monads/Applicative & al.
* Tests Impressive unit tests collection. Unfortunately, they are not that easy to follow. Approach like: // check a { }
// check b { } is not the best and I would encourage to add separate tests for both cases.
I would like to modularize the test suite. However, I have two main issues: - I want to avoid code duplication as much as possible - I want to reduce the compile-time of the test suite. It is already very long to compile, and putting more stuff in the same file helps to reduce this.
Would be great to have CI tests for run-time performance. I have seen charts, but the build could break when performance degradation occurred.
This is quite sophisticated, but a good suggestion and I would like to have that in the long term. Added this issue [3].
* Usefulness With C++11/C++14/C++17 template metaprogramming become a lot easier and a a lot of stuff might be written without need of TMP library at all. However, Hana is more than that, and I find it very useful. MPL and Fusions are/were extremely helpful and Hana is a huge step forward. *Frankly speaking, I would replace `std::tuple` with `hana::tuple` straight away.*
- Did you attempt to use the library? If so: * Which compiler(s) Clang 3.6/Clang 3.7 + libc++ (on linux/mac/windows) -> worked fine Tried on GCC-5.1 (on linux) without any success -> didn't link, but this issue is well known already
It should now link on GCC trunk, but other errors will pop up. Will try to fix this. Also, is Clang available on Windows? How so?
Tried on MSVC 2015-RC (just for a sake of trying -> didn't work ;)
* What was the experience? Any problems? I haven't experienced any blockers whilst trying the library. The only problem for me, is lack of support for MSVC. A lot of commercial projects requires MSVC as much as Clang/GCC.
- How much effort did you put into your evaluation of the review? I have been watching/trying Hana since April last year when I started to implement C++14 version of proposed boost.di library. I tried to re-implement C++03 version using Hana, but back then, Hana was crashing very often. Therefore, I decided to use plain C++14 features instead.
Hana used to use generic lambdas in its implementations. Since generic lambdas are a C++14 feature, you can guess that support for them was lacking (even in Clang). Because there were so many problems, and also because that prevented the library from being constexpr, I decided to remove lambdas from the implementation. That's probably why it's more stable right now.
I also went through all the source code/documentation/examples as well as played with the library.
Thanks Louis for a great library!
Thanks a lot for the review, Krzysztof. Also, I'd like to thank your for your interest in the library from the beginning and the bug reports you submitted a while ago. All this was helpful, especially when the library was at such an early stage. Regards, Louis [1]: https://github.com/ldionne/hana/issues/139 [2]: https://goo.gl/4XX5hc [3]: https://github.com/ldionne/hana/issues/140
On 6/18/2015 4:11 PM, Louis Dionne wrote:
Krzysztof Jusiak
writes: [...]
Compilation time: So I have written simple example to compare `Hana Map` and `C++ Tricks Map`. Please notice, I compared map with 1000 entries! Hehehe, can anyone imagine that with MPL or Fusion?
For the record, Hana's Map is not optimized right now. This is the subject of my GSoC project for this summer. So the performance should be pretty bad.
Results are here: tricks_map:
https://gist.github.com/krzysztof-jusiak/cb6633d6c11572c33928 0m0.095s
hana_map:
https://gist.github.com/krzysztof-jusiak/949d3916d84c466b80c5 0m11.105s
So, Hana seems to be much slower, but still not really slow. It's not hours, just a few seconds, which IMHO, it's a huge improvement already.
Actually, I think it is very good. Indeed, the current Map implementation is very dumb and lookup is done by doing a linear search inside a tuple. Doing a short-circuiting linear search in a 1k element Tuple without busting the recursion limit is, I think, an achievement by itself. Actually, I have to check why it works :-). Of course, this does not mean that the Map should not be optimized: it will, and I expect to match roughly the performance of a hand-written Map.
run-time: Haven't checked this part as deeply.
Diagnostic Messages: Really popular topic recently and Hana made a huge progress with it as well. Concepts helps a lot, but, unfortunately, there is always a call stack following the error message. Sometimes, such approach is desired, but would be great not to see all Hana's internals, especially with recursive algorithms.
I think this call stack is desirable, since it allows you to see where things blew up. Of course, there are a couple of levels of Hana-stuff in there, but you'll get the exact same thing if you instantiate a STL algorithm with an improper predicate. The only way to reduce the number of in-between steps would be to inline Hana's functions by-hand. I think language support would be needed to get significantly better diagnostics.
Also, if you'll notice, there are only two errors here. One is the actual error you made in the code, and the other one refers to a call to some deleted function `apply`. Usually, the compiler would explode and give a truck of error messages because it tries to continue compiling even after the error occurs. However, Hana will disable the next call when an error happens to make these useless messages disappear. That's where the call to a deleted function comes from.
Tested error message:
https://gist.github.com/krzysztof-jusiak/bfc51747d083e140772d
<aside> Ahaha! Finally I get this example I was looking for! To all of those that say "lambdas can't appear in unevaluated contexts because of implementation difficulties", I now dare say "Bullshit"! If you look at the above example, you'll notice that a lambda happily appears inside a `decltype(...)`. This is a Clang glitch (the only one I never reported) that only works in some specific circumstances, which allows us to have lambdas appear inside unevaluated contexts. This allows us to write type-level computations with value syntax inline, without ever needing to create an external variable.
I want lambdas in unevaluated contexts for C++17. Please. Also, people, please don't report this bug :-). </aside>
I also had some issue, when some include was missing. Compilation was fine, but the computation was run-time only. Would be great to somehow handle this problem. It's really tricky to understand, why it doesn't work as expected.
Can you share a link to that example? It would be helpful for me to see the exact thing so I can try to find a solution.
Debugging: Guess, in this matter, there is still no much progress. I tried Hana with MetaShell and TempLight, but, although, it was way better experience, it still was hard to debug the library. What about run-time algorithms? I haven't checked how hard it is to debug them, but I suspect it will be the same story as with STL, unless some magic is happening in HANA under the hood?
If your code compiles and you have a runtime bug, you can debug your code with a normal runtime debugger, just like you would do with the STL. You'll have to jump through a lot of function calls however, since heterogeneous algorithms can (in most cases) only be implemented recursively.
For debugging something that does not compile, I do not have a proper solution, and I think an external tool is really required. However, since Hana is functional in nature, it is often possible to extract large chunks of code and to just cut/paste stuff around to reduce your problem. Since there's no mutation, it's fairly straightforward. Of course, that is still not very satisfactory, but the problem is with C++.
* Documentation Documentation is really impressive. Honestly, love the search button! Would like to see more copy/paste examples tho. I'm really inpatient sometimes and when have to find part of the example at one place and figure out includes I do get easily annoyed. Related to that, would be great to always see which file has to be included for anything which is not included by `boost/hana.hpp`.
Ok, I will try to make the examples self-contained. See this issue [1].
As already mentioned, would be better to use hana::... instead of having an assumption for `using namespace boost::hana`. I would also add some tutorial for less experienced users with explanations what the monad is and how functional programming concepts are applied in Hana.
I think that explaining Monads is out of scope for Hana. What I can do is provide helpful links to existing tutorials, but I don't want to fall in the Monad Tutorial Fallacy [2]. I do agree that more extensive examples of how the functional concepts can be used in the specific context of metaprogramming would be helpful. I'll try to improve some of the examples given for Monads/Applicative & al.
* Tests Impressive unit tests collection. Unfortunately, they are not that easy to follow. Approach like: // check a { }
// check b { } is not the best and I would encourage to add separate tests for both cases.
I would like to modularize the test suite. However, I have two main issues: - I want to avoid code duplication as much as possible - I want to reduce the compile-time of the test suite. It is already very long to compile, and putting more stuff in the same file helps to reduce this.
Would be great to have CI tests for run-time performance. I have seen charts, but the build could break when performance degradation occurred.
This is quite sophisticated, but a good suggestion and I would like to have that in the long term. Added this issue [3].
* Usefulness With C++11/C++14/C++17 template metaprogramming become a lot easier and a a lot of stuff might be written without need of TMP library at all. However, Hana is more than that, and I find it very useful. MPL and Fusions are/were extremely helpful and Hana is a huge step forward. *Frankly speaking, I would replace `std::tuple` with `hana::tuple` straight away.*
- Did you attempt to use the library? If so: * Which compiler(s) Clang 3.6/Clang 3.7 + libc++ (on linux/mac/windows) -> worked fine Tried on GCC-5.1 (on linux) without any success -> didn't link, but this issue is well known already
It should now link on GCC trunk, but other errors will pop up. Will try to fix this. Also, is Clang available on Windows? How so?
If you build clang targeted for gcc RTL ( not MSVC ) on Windows you can use Boost Build with the current clang.jam file by just specifying toolset=clang. If you need help doing this just ask.
Edward Diener
On 6/18/2015 4:11 PM, Louis Dionne wrote:
[...]
It should now link on GCC trunk, but other errors will pop up. Will try to fix this. Also, is Clang available on Windows? How so?
If you build clang targeted for gcc RTL ( not MSVC ) on Windows you can use Boost Build with the current clang.jam file by just specifying toolset=clang. If you need help doing this just ask.
Thanks for the pointer. I don't have access to a Windows machine, but it might be useful to test on Appveyor with Clang. I'll have a look. Louis
For the record, Hana's Map is not optimized right now. This is the subject of my GSoC project for this summer. So the performance should be pretty bad.
Fair point. I will compare tuple then ;)
Actually, I think it is very good. Indeed, the current Map implementation is very dumb and lookup is done by doing a linear search inside a tuple. Doing a short-circuiting linear search in a 1k element Tuple without busting the recursion limit is, I think, an achievement by itself. Actually, I have to check why it works :-). Of course, this does not mean that the Map should not be optimized: it will, and I expect to match roughly the performance of a hand-written Map.
Actually it did reach the recursion limit. Had to add -ftemplate-depth=1100 or sth along them lines.
I think this call stack is desirable, since it allows you to see where things blew up. Of course, there are a couple of levels of Hana-stuff in there, but you'll get the exact same thing if you instantiate a STL algorithm with an improper predicate. The only way to reduce the number of in-between steps would be to inline Hana's functions by-hand. I think language support would be needed to get significantly better diagnostics.
Also, if you'll notice, there are only two errors here. One is the actual error you made in the code, and the other one refers to a call to some deleted function `apply`. Usually, the compiler would explode and give a truck of error messages because it tries to continue compiling even after the error occurs. However, Hana will disable the next call when an error happens to make these useless messages disappear. That's where the call to a deleted function comes from.
Yea, but from recursive algorithms the call stack may never finish. Imagine fold in fold in fold and error somewhere there. Will try to provide proper example later on.
Can you share a link to that example? It would be helpful for me to see the exact thing so I can try to find a solution.
I would like to modularize the test suite. However, I have two main issues: - I want to avoid code duplication as much as possible - I want to reduce the compile-time of the test suite. It is already very long to compile, and putting more stuff in the same file helps to reduce
Sure, will send with the other example above. Can't find it right now :/ this. Totally understand. Had the same issue with my library. Ended up with silly framework with no run-time overhead. I tried Boost.Test/Google.Test/Catch before, but the overhead was quite big. My approach: struct test { template<class Test> test(const Test& test) { test(); } }; and I'm writing tests like that: test my_test_case_name = [] { // test }; You can find example here: https://github.com/krzysztof-jusiak/di/blob/cpp14/test/ft/di_scope_exposed.c... With a bit of effort you can get XML output with test case name and error message as well. The good bit is, it compiles very fast and you don't have to register anything, which is always annoying.
It should now link on GCC trunk, but other errors will pop up. Will try to fix this. Also, is Clang available on Windows? How so?
You can find clang-cl for Windows here:
http://llvm.org/releases/3.6.0/LLVM-3.6.0-win32.exe
http://clang.llvm.org/docs/UsersManual.html#clang-cl
Cheers, Kris
On Fri, Jun 19, 2015 at 2:30 PM, Louis Dionne
Edward Diener
writes: On 6/18/2015 4:11 PM, Louis Dionne wrote:
[...]
It should now link on GCC trunk, but other errors will pop up. Will
try to
fix this. Also, is Clang available on Windows? How so?
If you build clang targeted for gcc RTL ( not MSVC ) on Windows you can use Boost Build with the current clang.jam file by just specifying toolset=clang. If you need help doing this just ask.
Thanks for the pointer. I don't have access to a Windows machine, but it might be useful to test on Appveyor with Clang. I'll have a look.
Louis
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
On 2015-06-18 22:11, Louis Dionne wrote:
Tested error message:
https://gist.github.com/krzysztof-jusiak/bfc51747d083e140772d
<aside> Ahaha! Finally I get this example I was looking for! To all of those that say "lambdas can't appear in unevaluated contexts because of implementation difficulties", I now dare say "Bullshit"! If you look at the above example, you'll notice that a lambda happily appears inside a `decltype(...)`. This is a Clang glitch (the only one I never reported) that only works in some specific circumstances, which allows us to have lambdas appear inside unevaluated contexts. This allows us to write type-level computations with value syntax inline, without ever needing to create an external variable.
I want lambdas in unevaluated contexts for C++17. Please. Also, people, please don't report this bug :-). </aside>
See this remark by Richard Smith: https://groups.google.com/a/isocpp.org/forum/#!msg/std-proposals/hAnVRTlsQZY... (plus some of the quoted text) According to him, the rule is dedundant by now, but removal of the rule is not on the core issues list yet. Thus, you might want add some input to the core issues :-)
Roland Bock
[...]
See this remark by Richard Smith: https://groups.google.com/a/isocpp.org/forum/#!msg/std-proposals/ hAnVRTlsQZY/vnaOykSka2UJ (plus some of the quoted text)
According to him, the rule is dedundant by now, but removal of the rule is not on the core issues list yet.
Thus, you might want add some input to the core issues
Thanks for the input. I'll try to do this when I get some time. Regards, Louis
participants (4)
-
Edward Diener
-
Krzysztof Jusiak
-
Louis Dionne
-
Roland Bock