On 06/24/2012 01:10 AM, Eric Niebler wrote:
I've made some good progress on the C++11 proto rewrite that I'd like to
share. So far, it's been a less radical shift than I expected.

You didn't try hard enough ;)

Expressions vs. Grammars
========================
Many new users are confused by the difference between terminal<int> and
terminal<int>::type. In proto.next, there is no difference. Forget the
::type. Things just work.

Neat

Custom transforms are simpler
=============================
Currently, defining a custom transform means defining a struct with a
nested impl class template of 3 parameters, correctly inheriting and
following a protocol. In the rewrite, I wanted to simplify things. Here
for instance, is how the _expr transform is defined:

     struct _expr
       : transform<_expr>
     {
         template<typename E, typename ...Rest>
         auto operator()(E && e, Rest &&...) const
         BOOST_PROTO_AUTO_RETURN(
             static_cast<E &&>(e)
         )
     };

A custom transform is simply a struct that inherits from
proto::transform and that has an operator() that accepts an arbitrary
number of parameters. (The use of BOOST_PROTO_AUTO_RETURN is not
necessary. It simply handles the return statement, the return type, and
the noexcept clause.)

Good

Data parameter uses a slot mechanism
====================================
In proto today, transforms take 3 parameters: expression, state and
data. As you can see from above, transforms in proto-11 take an
arbitrary number of parameters. However, that can make it hard to find
the piece of data you're looking for. Which position will it be in?
Instead, by convention most transforms will still only deal with the
usual 3 parameters. However, the data parameter is like a fusion::map:
it will have slots that you can access in O(1) by tag.

Here is how a proto algorithm will be invoked:

   int i = LambdaEval()(_1 + 42, 0, proto::tag::data = 8);
                                    ^^^^^^^^^^^^^^^^^^^^
The 3rd parameter associates the value 8 with the data tag. The _data
transform returns the data associated with that tag. Additionally, you
can define you own tags and pass along another blob of data, as follows:

   int i = LambdaEval()(_1 + 42, 0, (proto::tag::data = 8, mytag = 42));

The _data transform will still just return 8, but you can use
_env<mytag_type> to fetch the 42. The third parameter has been
generalized from an unstructured blob of data to a structured collection
of environment variables. Slots can even be reused, in which case they
behave like FILO queues (stacks).

How do you set up new tag  ? Is just mytag some

mytag_type mytag = {};

?

or should mytag_type inherit/be wrapped from some special stuff

As for what is not changing:

Grammars, Transforms and Algorithms
===================================
It would be wonderful if there were a more natural syntax for describing
proto algorithms rather than with structs, function objects, proto::or_,
proto::when, and friends. If there is one, I haven't found it yet. On
the up side, it means that many current proto-based libraries can be
upgraded with little effort. On the down side, the learning curve will
still be pretty steep. If anybody has ideas for how to use C++11 to
simplify pattern matching and the definition of recursive tree
transformation algorithms, I'm all ears.

There is not so much way to describe something that looks like
a grammar definition anyway. BNF/EBNF is probably the simplest
way to do it.

Now on the syntactic clutter front, except wrapping everything in round lambda
or use object/function call in a hidden decltype call, I don't see what we
can do better :s


Glad it is picking up steam :D

_______________________________________________
proto mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto

Reply via email to