|
Boost Users : |
Subject: Re: [Boost-users] [Proto?][Phoenix?] : Advice on creating lazy data structures
From: Eric Niebler (eric_at_[hidden])
Date: 2010-03-30 01:22:45
On 3/30/2010 2:02 PM, Manjunath Kudlur wrote:
> With Phoenix or lambda-like DSELs implemented with Proto, it is easy
> to implement stuff when the expected actual parameters to the lambda
> expressions are primitive types. When I want to pass arbitrary types
> to the lambda expression and manipulate it in the lambda expression,
> things become complex. For example, consider the following function :
>
> struct point {
> float x;
> float y;
> };
>
> float sum(point p) {
> return p.x+p.y;
> }
>
> If I want to have a lazy version of this function, I cannot simply do
> (arg1.x + arg1.y)(p). I have to implement functions that return Proto
> or Phoenix expressions and use it in the language. In the above case,
> it would look something like (point_get_x_(arg1) +
> point_get_y_(arg2))(p). So for every type I want to support in the
> DSEL, I have to implement lazy versions of functions to get and set
> the type members, or call some methods. In other words, the language
> has to be aware of all the data types that can be used with it.
<snip>
Not necessarily. These these can be added to your DSEL post-hoc, and
there are some fun games you can play with proto's operator->*. Consider
the following program:
#include <cassert>
#include <boost/proto/proto.hpp>
namespace proto = boost::proto;
struct point
{
int x, y;
};
proto::terminal<int point::*>::type x = {&point::x};
proto::terminal<int point::*>::type y = {&point::y};
struct arg_ {};
proto::terminal<arg_>::type arg = {{}};
struct micro_lambda
: proto::or_<
proto::when<
proto::terminal<arg_>
, proto::_state
>
, proto::otherwise<
proto::_default<micro_lambda>
>
>
{} eval;
int main()
{
point p = {2,4};
int r = eval( arg->*x + arg->*y, p );
assert( r == p.x + p.y );
}
You can't overload operator dot (.), but proto makes up for it by
automatically interpreting ->* as if it were dot. Proto evaluates the
LHS and RHS, and as long as the RHS is something like a data member
pointer or member function pointer that can be applied to the LHS, it
all Just Works.
It works with mutation through the data member pointer, too:
eval( arg->*x *= 21, p );
assert( p.x == 42 );
HTH,
-- Eric Niebler BoostPro Computing http://www.boostpro.com
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net