Boost logo

Proto :

Subject: Re: [proto] My own lambda for MSM / wish list
From: Thomas Heller (thom.heller_at_[hidden])
Date: 2011-03-14 09:01:08


On Monday, March 14, 2011 01:39:41 PM Christophe Henry wrote:
> Hi Thomas,
>
> >> Row < source_state , event , target_state, action , guard >
> >
> >I suggest you to look into spirit how semantic actions are dealt with, it
reminds me of exactly this:
> Ok I will, thanks.

Keep in mind, spirit uses Phoenix V2, but the idea is the same ...

> >Phoenix actors are POD, they are default constractible. Do you have a
> >testcase where this is not the case?
>
> Unfortunately no more, it was quite some time ago, maybe I did it with
> V2. I got something which was not usable by BOOST_TYPEOF.
> I'll try it again.
>
> >> std::set<int, BOOST_MSM_LPP_LAMBDA_EXPR(_1 < _2) > s2;
> >
> >As Eric noted, decltype is the answer. I can't see why this should not
> >be possible within phoenix.
>
> Wait, I'm confused, it IS possible, or it SHOULD be possible? Can I
> pass any valid phoenix expression? Not just a simple operator
> expression, but an if/else, while, or an expression made of several
> statements?
> I want an arbitrary phoenix expression.
> That I need a decltype is clear and what I'm already doing. But an
> expression containing references, pointers, or even an int would be of
> no use for a decltype.

Yes, this is a problem. I don't know how this can be solved without actually
passing the expression.

> >> std::transform(vec.begin(),vec.end(),vec.begin(), ++_1 + foo_(_1) );
> >
> >To answer your question, phoenix actors return their last statement. In
> >your case the result of ++_1 + foo_(_1) is returned.
>
> Hmmm now I'm lost. Just after you write that if_/else_ returns nothing.

See below.

> >> std::transform(vec.begin(),vec.end(),vec.begin(),
> >> if_(_1)[ ++_1,return_(++_1)].else_ [return_(++_1)] );
> >
> >Ok, if_(...)[...] and if(...)[...].else_[...] are statements in phoenix,
> >meaning they return nothing (aka void). The answer to your question is
> >to simply use phoenix::if_else which is in the operator module because
> >it emulates the ?: operator.
>
> Ok but this is just a partial answer, right? What about while / do or
> whatever I might need?
> I would like a clear statement: If I have an expression composed of
> any number of statements of any type and any order inside the full
> extent of phoenix (say if_().else_[], while_(), ++_1,fun_()), what is
> the return value?
>
> From what you write I understand "the last statement except in some
> cases". Which ones?

Calling phoenix expressions from the statement module return void.
Calling phoenix expressions from any other modules return whatever ...
depending on the "C++-Sense".
You might ask for example:
What does _1 + _2 return?

The answer is: It returns a callable expressions. When the expression gets
called with two arguments that call will return the result of the addition,
or however operator+ is overloaded for the types passed ...

In Phoenix you also have the overloaded operator, - which emulates
sequences.
Now there is no return statement in phoenix. A call to a phoenix expression
will return whatever expression (now talking in the C++ sense) the last
expression was, where a phoenix expression can be composed and is maybe
arbitrary complex.
This can be void or something totally different.

There are only some cases where the return value is fixed to a certain type.
In particular everything from the "Statement" module was defined to return
void to match the C++ semantics.

> >As Eric already noted, Phoenix captures everything by value. There is no
> >special syntax needed to capture other variables in scope (if you want
> >to capture them by value, meaning that they will get copied into the
> >phoenix expression). Your solution is similar to what is there in
> >phoenix already: Local variables and the let/lambda expressions. Your
> >examples will have your exact "better syntax":
> >
> >lambda[ _a = q ] [ _1 + _a /* first"captured" */]
> >
> >lambda[ _a = ref(q) ] [ _a++ /* first "captured" */ ]
> >
> >lambda[ _a = cref(q) ] [ _1 + _a /* first "captured" */ ]
>
> Ah perfect! This is what I'm looking for.
>
> >> Ok, these ones I didn't implement them, but I can dream.
> >
> >I am dreaming with you! :)
>
> Let's not dream much longer then ;-)
> We have here people who can do it.
>
> >By looking at these examples i can not see what's there that is not
> >provided by Phoenix already.
>
> Then it's perfect and what I want, but I'll need to give it a closer
> look. Mostly I want:
> - return values
> - the ability to decltype anything. For MSM it's about the same as the
> std::set case.
>
> If you allow a short criticism, I'd say that phoenix is great and
> maybe even offers all I want, but the doc is doing it a great
> disservice. I got so frustrated I started my own implementation and
> seeing my lack of time, it means something ;-)

Maybe you should have asked before you started re-implementing everything ;)

> What I think we need is:
> - more different examples showing what it can do, not the trivial
> examples it currently took over from V2

Phoenix comes with a whole bunch of testcases, which can be seen as examples
as well.

> - much much more about internals so that I don't come to the idea of
> implementing a solution for my own case

I tried to document the internals. What do you think is missing?
The questions you had could have all been solved by looking at the
documentation, there wasn't any need to know the internals.
Ok, I admit, the whole capture by value semantics probably isn't discussed
at full length.
Of course there is always room for improvement! Do you have anything
specific?

>
> Thanks,
> Christophe
> _______________________________________________
> proto mailing list
> proto_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/proto



Proto list run by eric at boostpro.com