Boost logo

Boost :

Subject: Re: [boost] Phoenix v3 review
From: Mathias Gaunard (mathias.gaunard_at_[hidden])
Date: 2011-02-25 07:31:16


On 24/02/2011 19:07, Thomas Heller wrote:
> On Thu, Feb 24, 2011 at 5:52 PM, Mathias Gaunard
> <mathias.gaunard_at_[hidden]> wrote:

>> ----
>> Phoenix v3 is missing a phoenix.hpp header file that includes all modules,
>> which Phoenix v2 had (but in the parent directory).
>
> Nope, its not, there is the boost/phoenix/phoenix.hpp header which
> includes all of phoenix.
> IIUC it is generally frowned upon to put those headers directly in the
> boost directory.

It must be recent then, because I didn't have it in my not entirely up
to date checkout of the sandbox.

>
>> Lazy functions
>> --------------
>> Using phoenix::function to turn a PFO into a lazy function is the most basic
>> way to extend Phoenix with new functionality, and clearly the recommended
>> way to do so according to the docs. [1] [2]
>> It is directly inherited from Phoenix v2, and only the result type deduction
>> mechanism changed.
>
> Correct. But please keep in mind. You as a user don't have to put your
> phoenix::function objects at some namespace scope.
>
>> This approach has several problems, at least in the way it is presented in
>> the documentation.
>> - global objects potentially increase binary size
>> - those objects are not PODs and therefore requires runtime initialization,
>> adding some runtime overhead at application startup
>> - instantiation happens regardless of whether the function is used or not,
>> which affects compilation time negatively.
>
> Do you have numbers for that?
>
>> This method is massively used to define a whole lot of lazy functions that
>> forward to standard algorithms and container functions [3], which suggests
>> that this is indeed the recommended way to proceed.
>> It should however be avoided; prefer defining a template function that
>> constructs and applies the adapted function object, if the function object
>> can stay a POD that's better too.
>
> Do you have concrete proposal how this could look like?
> If there is no significant impact on (compile and runtime) performance
> of the points you mentioned above, it will stay as it is for now.
>

I'll let Joel Falcou do that.

> It is not redundant. The thing is that proto only recognizes one tag
> for a terminal expression. To distinguish between all those different
> terminal types, we needed the custom terminal customization point.

I was thinking phoenix::ref could be a proto node, but that doesn't
quite work because Proto catches terminals by value (isn't there a way
to customize that though? -- I'm not familiar with that kind of thing)

>
>> Phoenix as Proto with statements
>> --------------------------------
>>
>> One thing I was hoping Phoenix v3 would be is Proto extended to support
>> statements.
>
> I don't understand, what do you mean by that?

Proto is a tool to write domain-specific embedded languages based on C++
expressions.
It's like a compiler framework, but the AST is limited to expressions
and cannot contain function creation, local variable definition, or
repetition.

It would be nice to have a tool like Proto but that was extended to deal
with more C++ language constructs. Even if the syntax to call them
requires transforming those constructs to expressions with a DSEL of its
own, at least there can be a canonic way to do so.

>> While it comes pretty for some uses, it still fails one one point: the
>> ability to define custom languages that embed Phoenix statements.
>
> The ability is there ...
>
>> The missing piece is handling of domains (extends are missing too, but I
>> don't think they make sense at the statement level).
>
> ... and you don't need necessarily need the proto domain feature for that.

Phoenix doesn't really help with things like

phoenix::if_(1)[some_expr_in_my_own_domain]

If things are necessarily in the phoenix domain, that's not really your
custom language.
That's like using Proto without domains.
I think it needs to be a parametric domain, like phoenix of common
domain of what's inside.

Being able to tell how Proto expressions within Phoenix should be
evaluated on a per-domain basis seems important too.
I have no idea how to evaluate a Phoenix expression containing other
Proto expressions with the current design.

>> Documentation
>> -------------
>> <http://svn.boost.org/svn/boost/sandbox/SOC/2010/phoenix3/libs/phoenix/doc/html/phoenix/actor.html>
>> doesn't talk about perfect forwarding.
>
> It is mentioned here:
> http://svn.boost.org/svn/boost/sandbox/SOC/2010/phoenix3/libs/phoenix/doc/html/phoenix/inside/actor.html#phoenix.inside.actor.function_call_operators

Yes, but the page I referenced shouldn't only list non-const reference
overloads: that's confusing.

> We can only *emulate* perfect forwarding. THe sentence you claim is
> wrong is just a reformulation of the "Perfect Forwarding Problem"
> (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm)
> problem statement.

Then the original problem statement is misleading.
It is later said in the paper that they don't consider solutions that
scale worse than linearly to be good enough.
Solution #3, that they do list, works fine with C++03 language rules,
but is discarded due to its cost in number of overloads.

I don't really see where the term "emulation" comes from. Forwarding
arguments is forwarding arguments, you just have to make sure you can
catch all arguments without loss of information, there is no hack or
emulation involved.

A better phrasing would involve saying that is is not impossible, but
rather requires an impractical amount of work.
I wonder how much that amount of work is really a problem with
preprocessed Phoenix though.


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