Boost logo

Boost :

Subject: [boost] [Phoenix] Some questions and notes...
From: Giovanni Piero Deretta (gpderetta_at_[hidden])
Date: 2008-09-24 12:47:41


Hi all,

I'm writing a review of phoenix, but first I have a some questions and notes.

* First of all, it is not clear to me how 'lambda' works. I would have
thought that it just introduced a new scope, but it seems that it does
something more:

1: int i = 10;
2: cout << arg1(i) <<endl;
3: cout << lambda[ arg1 ](i) <<endl; // doesn't compile
4: cout << lambda[ arg1 ]()(i)

The use of lambda at line 3 is completely superfluous, nevertheless, I
prefer that syntax because it makes it clear that I'm using a lambda
expression (always using lambda will also allow some other tricks I'll
discuss later). Surprisingly, line 3 doesn't compile.
lambda::operator[] actually returns a nullary stub that must be
evaluated to actually get our unary function. Is this really
necessary? can it be fixed?

* non-standard result<> protocol. IMHO for Phoenix to become a first
class boost library, it should support result_of out of the box. I
understand that this is not done for backward compatibility, but I
think that there are three solutions:

1) old users will still be able to use the Phoenix inside spirit if
they have a large codebase that uses the old protocol.
2) phoenix could provide a wrapper that converts from the old to the
new protocol and viceversa. This would require some changes in the
client code.
3) phoenix could detect the protocol used by the user function and
switch between the old and new 'result'. This is hard to do in a
robust way, but breaks no user code.

I would prefer the first option.

* Perfect forwarding. I'm used to the perfect forwarding in boost
lambda (which, contrary to what the documentation states, perfectly
forwards up to 3 args). Personally have little use for lambdas that
take their arguments by non const reference as I strive for
referential transparency.

I know that implementing this feature has an high compile time cost,
but there should at least be an option to enable it. I would vote for
two additional 'lambda' syntaxes: clambda and plambda (better names
are wellcome). The first one would work like boost lambda
const_arguments and should have no compile time cost, while the second
will do perfect forwarding up to some parameter number. This would
require the lambda[] syntax to actually return the wrapped function
object, not a stub (as per first question).

* operator->*. I sometimes use this operator with boost lambda, as a
short hand for binding member functions, but, as in phoenix, it
requires it lhs to be a pointer. Would it possible to extend it to any
functions? for example:

struct foo {
   int bar;
};

std::vector<foo> in =...;
std::vector<int> out;

std::transform(in.begin(), in.end(), std::back_inserter(out),
(&arg1)->*&foo::bar);

The parenthesis, and ampersand are ugly, it would be great if this worked:

std::transform(in.begin(), in.end(), std::back_inserter(out), arg1->*&foo::bar);

I think this would interfere with foo implementing its own
operator->*. Which brings the question...

* ... how do I implement type deduction for the my own overloaded
operators? I.e. what is the phoenix equivalent of
http://tinyurl.com/4botne ? By reading of the documentation I couldn't
figure out an easy way to do it.

Well, that's all for now, those questions are mostly to get the
discussion rolling, more to come.

-- 
gpd

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