Boost logo

Boost :

From: Eric Niebler (eric_at_[hidden])
Date: 2008-03-15 15:57:29


Markus Werle wrote:
> Hi!
>
> This is a minor issue, but nevertheless I'd like to share
> my opinion on this:
>
> The longer I think about _arg0 and its brothers and sisters
> the more I get the impression that they should be banned from proto.
>
> 1. Especially the typedefs for _arg, _left and _right should be
> removed from the library, because they duplicate the interface
> and bring more confusion than convenience.
<snip>
>
> Summary: I strongly vote against _arg, _left and _right.

I tend to disagree about _arg, _left, and _right. Should I also remove
the free functions proto::arg(), proto::left() and proto::right()? It's
true, you can use arg_c() for everything, but IMO you have to look
closely to see and appreciate the difference between "arg_c<0>(expr)"
and "arg_c<1>(expr)", but left(expr) and right(expr) are immediately
recognizable and readable. And most C++ operators are binary.

> 2. From a user's point of view I still cannot see the advantage
> of using argSOME_NUMBER instead of arg_c<SOME_NUMBER>.
> Couldn't you make arg_c<XX> a first class citizen of namespace proto?

I can't because proto::arg_c already exists, and it's a free function.
However, there is proto::_arg_c<>, which is a synonym for
transform::arg_c<>.

A word about that. Proto reuses names. proto::X is a function,
proto::result_of::X is a metafunction that computes the result type of
proto::X, proto::functional::X is the function object equivalent of X,
and proto::transform::X is the primitive transform equivalent of X. You
can't import all these namespaces without making X ambiguous. For the
most part, you don't want to, but transforms are different. You very
often want to be able to refer to arg_c the function and arg_c the
transform in the same bit of code. Qualification like "transform::arg_c"
is tedious and makes transforms hard to read. That's why the transforms
have equivalents in the proto namespace with a leading underscore.

I've always felt this is a little unsavory, but I haven't thought of
anything better. I'm open to suggestions.

> So even if it makes it easier to write the boilerplate parts
> of proto itself, names based on MACROS are still evil enough to
> remove them from the _interface_ and for me _argSOME_NUMBER
> is part of the interface.

Macros? These are not macros, they're typedefs.

> IMHO templates with integer arguments scale well enough not to
> introduce PP garbage here. I have the suspicion that _argSOME_NUMBER
> is only inside because you have all those
> BOOST_PP_MAKE_MY_CODE_WRITE_ONCE_NEVER_UNDERSTAND_LATER.

???

> Note that this is not a show stopper for me, I propose the ban,
> but in contrast to _arg, _left and _right I can live with those, since
> transform::arg_c<I> is at hand and I will use those right from the
> beginning and ban _arg0 from my own code consequently.
> <kidding>Eric, you will only have to pay for all those extra
> "transform::" I have to type all the time. Let's say $0.02
> for every occurence ... OK?</kidding>

So you also feel that typing transform:: over and over is a pain!

> Eric, please classify right from the beginning, whether issue #2
> takes on "bike shed characteristics" and/or disclose your
> rationale for _argSOME_NUMBER.

I'm really sorry now about that bike shed comment. :-(

I may be wrong, but it's possible that after you write some transforms,
your opinion on this issue will change. The qualification and the angle
brackets really obscure what a transform is doing. Consider the
difference between these two:

Use only transform::arg_c<>:
     struct MakePair
       : when<
             function<terminal<make_pair_tag>, terminal<_>, terminal<_> >
           , make_pair(
                 transform::arg_c<0>(transform::arg_c<1>)
               , transform::arg_c<0>(transform::arg_c<2>)
             )
>
     {};

Use shorter typedefs:
     struct MakePair
       : when<
             function<terminal<make_pair_tag>, terminal<_>, terminal<_> >
           , make_pair(_arg(_arg1), _arg(_arg2))
>
     {};

They mean the same thing, but the second is a vast improvement, IMO.
Proto uses function types to compose primitive transforms. Too many ::'s
and <>'s break it up and obscure the meaning.

If I get rid of the _argN typedefs, the examples in the documentation
will look very imposing.

-- 
Eric Niebler
Boost Consulting
www.boost-consulting.com

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