Boost logo

Boost :

Subject: Re: [boost] Review Request: Variadic Macro Data library
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2011-02-21 20:59:36

On Mon, Feb 21, 2011 at 7:18 PM, Paul Mensonides <pmenso57_at_[hidden]> wrote:
> On Mon, 21 Feb 2011 18:40:17 -0500, Lorenzo Caminiti wrote:
>> On Mon, Feb 21, 2011 at 2:37 PM, Paul Mensonides <pmenso57_at_[hidden]>
>>> I take serious issue with anything that intentionally perpetuates this
>>> mentality.  It is one thing if the syntax required is the same by
>>> coincidence.  It's another thing altogether when something is done to
>>> intentionally make it so.
>> It might be useful to discuss this topic using the Boost.Local `PARAMS`
>> macro as an example.
>> IMO, the following syntax is better from a pp metaprogramming
>> prospective because the arguments are a proper pp data structure (i.e.,
>> a sequence) and it is very clear from the syntax that you are invoking a
>> macro:
>> int BOOST_LOCAL_FUNCTION_PARAMS( (int x) (const bind this) ) { // [1]
>>     ...
>> l(-1);
>> However, from the users' prospective the following syntax is preferred
>> because it looks more like a C++ function parameter declaration so they
>> are more familiar with it:
>> int BOOST_LOCAL_FUNCTION_PARAMS(int x, const bind this) { // [2]
>>     ...
>> l(-1);
>> Therefore, as a pp metaprogrammer I'd prefer [1] but as the Boost.Local
>> library developer I must keep in mind my users' preference and also
>> provide [2] when variadics are available.
> There is such a thing as good/bad regardless of preference.  In the
> second case above, you've traded compilation efficiency for a minor
> syntactic difference.  As a library developer, particularly in the case
> of a general purpose library, that's a bad call to make.  If you provide
> both of the above, at least you still have the efficient version that
> doesn't waste time doing a format conversion, but now you've introduced
> bloat into the interface.  You have two ways to do the same thing--one of
> which is (apparently, given the existence of the former) non-portable as
> well as brittle as far as revision is concerned.  What happens when you
> want to add some option--LOCAL_FUNCTION_PARAMS(option, (int x)...)?  In
> the latter case, because the preprocessor has no type system, that change
> is radical.  In the former case, you can do what I've been talking about
> with BOOST_PP_TUPLE_ELEM (et al) and produce a smooth, non-breaking
> revision path.  Instead, you end up with yet another interface point
> LOCAL_FUNCTION_PARAMS_WITH_OPTION that avoids the problem while adding
> yet more interface bloat.

I do understand your arguments about flexibility and extensibility of
the pp-sequence interface but my library's users want the
variadic-tuple syntax and that's essentially a fact for me as the
library developer... The argument that the sequence is more flexible,
etc just didn't work because at the end of the day the extra sequence
parenthesis look ugly and people don't even want to try to type them
(I wonder if that simply means that local functions are not really a
wanted feature because I would type the extra parenthesis if I needed
the functionality...).

> Perhaps this LOCAL_FUNCTION_PARAMS is a bad example for potential
> revision, but the above is referring the general case.  As I said
> previously, the only way that I would ever provide a macro interface (in
> a non-preprocessor metaprogramming library) such as the latter above, is
> if I was absolutely certain that no arguments would be added or removed.
>> IMO, it would be nice if Boost.Preprocessor supported variadics to make
>> metaprogramming [2] easy. However, that does not necessarily mean
>> providing:
>> I would find having these two macros just as useful (and perhaps more
>> correct):
>> #define BOOST_PP_TO_TUPLE(...) (__VA_ARGS__) BOOST_PP_TUPLE((...))
> What is BOOST_PP_TUPLE((...))?

Yes, sorry for the confusion... with BOOST_PP_TUPLE((...)) I meant

>> Then at some point in my pp metaprogram, I will have
>> `BOOST_PP_TUPLE(BOOST_PP_TO_TUPLE(__VA_ARGS__))` which would be as
>> convenient for me (a pp metaprogrammer) to use as
>> `BOOST_PP_TUPLE(__VA_ARGS__)` directly. Of course, the
>> `BOOST_PP_TO_TUPLE(__VA_ARGS__)` invocation will be hidden inside
>> `BOOST_LOCAL_FUNCTION_PARAMS(...)` expansion to respect my library
>> users' request that the `PARAMS` macro invocation should look like a
>> normal C++ function parameter declaration as much as possible.
> It is a DSEL.  By definition it has its own syntax--as it obviously
> already does.
>> In summary, I would think that providing `BOOST_PP_TO_TUPLE(...)` and
>> `BOOST_PP_TUPLE((...))` is a good approach.
> In the case of a tuple, why would any of the above be better than simply
> (__VA_ARGS__)?  Again, though I don't know what you're referring to by
> BOOST_PP_TUPLE((...)).  What is that macro supposed to do?

So: In summary, I would think that providing `BOOST_PP_TO_TUPLE(...)`
and `BOOST_PP_TUPLE_TO_SEQ((...))` is a good approach. And I could
personally also live with doing `(__VA_ARGS__)` directly before
invoking `BOOST_PP_TUPLE_TO_SEQ((...))` instead of using

On Mon, Feb 21, 2011 at 7:18 PM, Edward Diener <eldiener_at_[hidden]> wrote:
> On 2/21/2011 6:47 PM, Lorenzo Caminiti wrote:
>>> In summary, I would think that providing `BOOST_PP_TO_TUPLE(...)` and
>>> `BOOST_PP_TUPLE((...))` is a good approach.
>> Sorry, when I said `BOOST_PP_VARIADIC_TUPLE(...)` and
>> `BOOST_PP_TUPLE((...))` I meant of course
>> `BOOST_PP_TUPLE_TO_SEQ((...))` (or some other pp tuple macro but
>> without the size argument).
> I am oppose to such redundancy. I think BOOST_PP_TUPLE_TO_SEQ(...) is
> enough.


Boost list run by bdawes at, gregod at, cpdaniel at, john at