Le 11/03/2016 01:50, Paul Fultz II a écrit :
On Thursday, March 10, 2016 at 5:26:38 PM UTC-6, Edward Diener wrote:
On 3/10/2016 1:46 PM, Paul Fultz II wrote:
On Thursday, March 10, 2016 at 12:34:26 AM UTC-6, Vicente J. Botet
wrote:
I will put all of them in the advanced section. I would no mention them in the introduction as the user can create the HOF locally or use a factory.
Being able to declare the functions as global variables is a key feature of the library. The example in the quick start guide shows how to implement many things without the need for a lot of template boilerplate. For those users that prefer not to use global function objects(and I have yet seen a compelling reason not to use them) can look at the 'Advanced' section.
I realize now, that I need to spend more discussing the advantages of using global function objects(more composability), and address some of the misperceived issues with these global function objects(they can be in a namespace to avoid name conflicts and are not mutable so it won't be a problem in mutilthreaded environments). You do need to explain why "global variables" is a key feature of the
Escriba library. I cannot understand from your docs why there is any disadvantage instantiating Callables locally as opposed to globally other than the usual fact that a local object can go out of scope.
We can define functions by simply composing other functions together and we don't need to write awkward syntax nor template boilerplate for it. For example, we can simply write `make_tuple` like this:
BOOST_FIT_STATIC_FUNCTION(make_tuple) = by(decay, constructstd::tuple());
Alternatively, you could write a factory function for this instead:
constexpr auto make_tuple() { return by(decay, constructstd::tuple()); }
This function should be names maker_tuple at it builds an adaptor :)
Of course this requires the user to write `make_tuple()(xs...)`, which I don't think any user would expect this, especially since `std::make_tuple` doesn't work like that. So instead, it can be wrapped in a template function:
template
constexpr auto make_tuple(Ts&&... xs) -> declype(by(decay, constructstd::tuple())(std::forward<Ts>(xs)...)) { return by(decay, constructstd::tuple())(std::forward<Ts>(xs)...); } Which is a lot of boilerplate to compose some simple functions.
These are the kind of things that can be described in an advanced section?
If there really is some other reason it is completely lost to me. If you would like to point to me in your doc where you explain the use of "global variables" as being a key feature of your library or as being necessary to use the functionality of your library, I would be glad to read about it and ask further about it here.
It is not a necessary feature, but it is an important feature nonetheless, and I need to spend more time explaining its usefulness.
I believe all agree that the feature is useful for those that want to declare global HOFs. Some don't like global variables representing functions other don't like macros. The library is useful for those people too.
If, OTOH, it is just your preference to use global objects as opposed to the various forms of local instantiation, I really wish you would just say that rather than acting like your library does not work correctly somehow other than with global variables.
This is not the case. You can declare local variables for these HOF or define functions that return these HOF. What is not simple with the current language is to declare them as global variables, and this is the design rationale for those macros.
The composability of the adaptors and functions applies to both global and local functions. The adaptors provide a simple way to create functions to be passed locally, such as creating a comparator for std::sort(ie `std::sort(first, last, by(&employee::name, _<_))`). However, they can also be used to define global/free functions in a much simpler way as well(such as writing `std::make_tuple`), which I think is equally important.
Furthermore, in a quick start guide or introduction, I want to be able to demonstrate the capabilities of the library in a way to show its usefulness, and why someone would choose to use this library. Perhaps, you are ok with awkward syntax or template boilerplate in writing your functions, and would prefer to only use the adaptors for local functions. However, there are others who will find writing global function objects with the adaptors very useful, so I want to be able to show those capabilities in the introduction of the library. I do, however, need to discuss some of the misperceived issues with using global function objects in the documentation. As the issues raised in the review were:
1) Namespacing - This is not a problem because all global function objects can be placed in a namespace. This is obvious. There is no issue here.
2) Global state - This is not a problem either, because `BOOST_FIT_STATIC_FUNCTION` declares the function object const with constexpr. So there can be no mutable or changing state internally in the object, and it must be constructed without side effects.
I think addressing these concerns in the documentation will help put users at ease when using global function objects, so they have no problem taking advantage of the adaptors to build function objects globally.
Maybe I have missed something but I have the intuition that many others have missed it likewise, from the responses of others about this issue.
I agree with your intuition, and I believe the documentation should spend more time discussing these issues. I hope my email has made it somewhat clearer to you.
Best, Vicente