Boost logo

Boost :

Subject: Re: [boost] [Fit] Review
From: Edward Diener (eldiener_at_[hidden])
Date: 2016-03-11 01:18:48


On 3/11/2016 12:10 AM, Paul Fultz II wrote:
>
>
>>>
>>> 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,
>>> construct<std::tuple>());
>>
>> What is the type of by(decay,construct<std::tuple>()) ?
>>
>
> It is something like `by_adaptor<decltype(decay), construct<std::tuple>>`.
>
>
>> I thought I would be able to write locally:
>>
>> auto make_tuple(by(decay,construct<std::tuple>()));
>>
>> but evidently you are saying that does not work.
>>
>
> That is not what I am saying at all. It can work, the functions can be used
> locally, like in the first example. However, for `make_tuple` this is not
> useful at all. If `std::make_tuple` was assigned to a local variable then no
> one could ever call the function.

I don't understand this. I have a 'make_tuple' callable above and if I
want to use it somewhere else I pass it to whatever functionality needs
it. You, instead want things to be global so that they can be used by
other functionality without passing anything around. Isn't this just an
argument about programming style ? I don't mind if you like your
programming style but I doubt I am the first or last programmer who
prefers variables created and used when needed. In fact I have a very
strong suspicion that "my" programming style is that of the majority of
C++ programmers and that only a minority of programmers like global
variables even if they can be global within a namespace scope. So what I
am essentially saying is that while I understand you like your style and
your macros for creating "global" callables, inferring that this is
central to using your library, when it is not AFAICS, is going to lose
you end-users as well as misrepresent your library. I see much more
plusses to your library if the result of using your adapters,
decorators, functions, and utilities can be instantiated anywhere and
used in ways that any variable in C++ can be used. if however there are
real technical limitations, as opposed to "I like this style because I
it is easier for me to use with Fit", of using Fit functionality to
create "local" objects I think you need to spell out what those
limitations are.

> So you use global function objects when
> you
> want to make the function available for consumption by others. And the
> advantage of defining `make_tuple` this way over writing it as it is written
> currently in the standard library, is that we can avoid all the template
> boilerplate involved with this.
>
>
>>>
>>> Alternatively, you could write a factory function for this instead:
>>>
>>> constexpr auto make_tuple()
>>> {
>>> return by(decay, construct<std::tuple>());
>>> }
>>>
>>> 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<class... Ts>
>>> constexpr auto make_tuple(Ts&&... xs)
>>> -> declype(by(decay,
>>> construct<std::tuple>())(std::forward<Ts>(xs)...))
>>> {
>>> return by(decay,
>> construct<std::tuple>())(std::forward<Ts>(xs)...);
>>> }
>>>
>>> Which is a lot of boilerplate to compose some simple functions.
>>>
>>>
>>>> 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.
>>>
>>>
>>>> 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.
>>>>
>>>
>>> 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.
>>>
>>> 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.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk