On Wednesday, March 9, 2016 at 2:33:55 AM UTC-6, Vicente J. Botet Escriba wrote:
Le 09/03/2016 08:34, paul Fultz a écrit :
On Tuesday, March 8, 2016 4:58 PM, Vladimir Batov <
On 03/09/2016 08:43 AM, paul Fultz wrote: ...I guess people have different ways of learning a library. I wonder what is needed to be explained better in a initial overview of the library. Please do not take it a a criticism of any kind. That's just an impression I've got. I could be way off the mark.. I often am... I read the docs... twice... well, I tried... :-) I was not able to find an answer to a nagging question -- why I might need the library? What does it do that the standard C++ does not? To me the Quick Start felt more like Quick Start to Confusion. :-) Literally I felt like the deeper into the docs I was going the more alarmed I was. Maybe I need a little more explanation of components in the Quick Start Guide. Perhaps, also, a comparison of writing some of the examples without using the library. The recursive print example is simple, but the technique could apply anytime you needed generic serialization of data. I have written code
that without using this library, so I can see benefit of using it for
Vladimi...@constrainttec.com javascript:> wrote: like this
particular case. So perhaps, writing a comparison without the library might make that clearer. Yes, please, show us some examples.
I do show some comparisons here: http://pfultz2.com/blog/2014/12/06/compare-overloading-1/ http://pfultz2.com/blog/2014/12/12/compare-overloading-2/ I should try to integrate them into the documentation.
"We can make it (the functor) behave like a regular function" I assume by functor, you mean function, as the library doesn't support functors and is beyond the scope of this library. Some parts of the C++ community name a function object a functor. It ha nothing to be with the applicative, functor, monad in type classes.
In all honesty I don't think I ever had such a need. Usually IMO the conversion is the other way around -- a reg. function into a functor. I think it happens pretty much automatically. Well, the library provides help for that as well, because currently in C++ you can't pass generic functions to other functions, like this:
std::accumulate(v.begin(), v.end(), 0, std::max); // Compile error
However, BOOST_FIT_LIFT will let you do that:
std::accumulate(v.begin(), v.end(), 0, BOOST_FIT_LIFT(std::max)); Maybe it is worth noting that these is a C++17/20 proposal to manage with this case.
[1] p0119r1 - Overload sets as function arguments http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0119r1.pdf
Thanks for the link, I will add a reference to that.
"if we construct the class as a global variable"
Should I be excited about it? Globals are often a royal pain. Do I want to construct it a a global variable? | Whats the pain about these Global variables? They are const, can be namespaced, and work just like free functions. However, they do have
advantages.
First, by making them objects we can turn functions into first-class citizens. Note that we do that now with function objects and lambdas. This is a major argument that belongs to the motivation. You library works with and build high order functions (HOF). This allows for functions to be easily passed around to other functions. In fact, almost all the functions in this library are declared this way. This make the functions(and adaptors) easily composable. For example, if you wanted to write a function to do for_each over a tuple, you can easily compose
several the
`unpack` adaptor with the `by` adaptor:
BOOST_FIT_STATIC_FUNCTION(for_each_tuple) = compose(unpack, by); As others have noted you should separate the the high order function definition from the possibility to define them globally.
auto for_each_tuple = compose(unpack, by);
An alternative to use global function is to define function factories
auto for_each_tuple() { return compose(unpack, by); }
Alternatively, you could be written like this:
template
However this needs an extra level of parenthesis
for_each_tuple()([](auto x) { std::cout << x << std::endl; })(t);
Maybe it is worth talking of what is behind this style (point-free style or tacit programming)
Yes, thats a good idea.
So the `by` adaptor will call a function for each parameter, and the
adaptor will unpack the elements of the tuple to each parameter. By composing them together we can call a function for each element in a tuple. So, you can write a function to print each value in a tuple, like this:
auto t = std::make_tuple(1, 2); for_each_tuple([](auto x) { std::cout << x << std::endl; })(t);
So by passing functions to other functions, we can easily write some very sophisticated functions without having to resort to metaprogramming. Just as a comparison, here is how you could write for_each_tuple without this
`unpack` library:
namespace detail { template
void for_each(T&& t, F f, seq ) { auto l = { (f(std::get<Is>(t)), 0)... }; } } template
void for_each_tuple(std::tuple const& t, F f) { detail::for_each(t, f, detail::gen_seq ()); } It is more code, with more C++ cleverness going on.
This is s a good example, and of course will need to compare performances at compile time and run-time.
Secondly, by making them objects, it allows us to decorate or enhance functions. C++ doesn't have support for python-like decorators, so if
to enhance a function, it will need to be a function object through and through.
"BOOST_FIT_STATIC_FUNCTION" | A macro? For C++14? Really? And given you mention it about 20 times just in the Quick Start section it seems quite pivotal for the library... Should I be excited about it? Macros are often a royal pain... Wrapping functors and lambdas in a macro?.. seems like I need quite a bit of I agree with that and I suggested Paul from the beginning to move this to an Advanced section. The fact that the library uses it to define the global function is of no concern for the users. Only if a user wants to define a global HOF, then those macros can help
you want them.
Its not just needed for HOF, you need it to define any global function. I could show alternative way of defining them without the macro, using a free function. However, I would prefer to move the non-macro version to the advance section, since it a little more complicated, whereas the macro is much simpler.
convincing I might want that.
C++17 will be adding support for inline variables, so in the future this macro will be unnecessary. For now, it will take care of statically initializing the function and avoiding possible ODR issues. Any reference to something that will appear in the future standard and describe that your macros are a way to emulate a future feature would be much appreciated. Could you elaborate how inline variables are related?
I'll try to find the papers that was written on them.
Furthermore, dealing with inconsistencies and bugs across multiple
is a real pain. For example, MSVC has lots of bugs with constexpr that can affect statically initializing the function object. Not everyone needs constexpr. So maybe this use case should be moved to
platforms the advanced usage.
However, the user needs constexpr, even if the function is not constexpr, if they want to initialize the variable statically.
AN alternative that you could or not have is to require better compilers. as e.g. Boost.Hana does.
However, I would like portability.
So this macro provides workarounds so the it can be initialized statically. I don't see the macro as problematic, and without the macro is more problematic. Only if the user needs to declare them globally.
Yes.
However, you can write it without the macro like this:
template<class T> struct static_const_storage { static constexpr T value = T(); };
template<class T> constexpr T static_const_storage<T>::value;
template<class T> constexpr const T& static_const_var(const T&) { return detail::static_const_storage<T>::value; } I believe that there are a lot of users that would prefer to write the code that follows once a library provide the previous one static constexpr auto&& for_each_tuple = static_const_var(compose(unpack, by));
This of course, will only work on a fairly compliant C++11 compilers. It doesn't work on MSVC. Does it works with a MSVC C++14?
It doesn't, or at least it is problematic. First, the variable does not have a unique address across translation units. Secondly, there is problems when this is combined with pre-compiled headers. And thirdly, as mentioned before, the constexpr bugs can make this not work at all. So the macro takes care of all these issues for the user, and I would rather not promote writing something that is not portable.
Also, it won't work when using lambdas. No doubt, C++14 gets rid of a lot of macro usages, but C++14 is still lacking in many areas, so macros are still needed to fill in these gaps. You need to let the user choose. If the user is using a C++14 compliant compiler, would it need the macros?
For lambdas yes. In C++17, all these macros will be unnecessary.
If not it is not worth presenting it as something capital. This belong to the workaround and emulations and I could appreciate having those macros, but having the equivalent C++ code is better.
The macros are there so the user doesn't have to think about whether they need a workaround or emulation. I could add an advance section that explains how to some these things without a macro with a note about portability. The thing is I want something simple the user can start with when using the library. Explaining a construct that has caveats should go in the advance section. The macro does not have caveats.
For a library to be accepted the user has to understand the purpose/value of it and to get excited about it. I did not get it. In fact, I got the opposite... but I a not the brightest "bulb" in the pack...
Thanks for the feedback, I probably should discuss more of the
using function objects in the documentation to make it clear to more
advantages of people. Yes I've said not all the people knows about High order functional programming. You should explain and make reference to external resources as needed.
Yes, good point.
Best, Vicente
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost