On Fri, Oct 15, 2010 at 1:35 AM, Thomas Heller <thom.heller@googlemail.com> wrote:
On Wednesday 13 October 2010 07:10:15 Eric Niebler wrote:
> I had a really hard time grokking unpack. In Proto, function-types are
> used to represent function invocation and object construction. The type
> "X(A,B,C)" means either call "X" with three arguments, or construct "X"
> with three arguments. In "unpack< X(A, B, C) >" X does *not* get called
> with three arguments. It gets called like "X( A(_0), A(_1), A(_2), ...B,
> C )", where _0, _1 are the child nodes of the current expression. This
> will confuse anyone familiar with Proto. I'd like to replace this with
> something a little more transparent.

Ok, i put to together an alternative version. This hooks onto the already in
place transform mechanism and works like this:
Whenever the first argument to a transform is proto::vararg<Fun> it expands
the child expressions and applies the Fun transform before the actual
transform gets called, example:

struct test
   : proto::when<
       proto::function<vararg<proto::_> >
     , foo(vararg<proto::_>)
   >
{};

this will call foo(a0, a1 ... aN) where aX are the children of the function
expressions. Note that you can replace proto::_ by any transform you like.
Thus making the call look like:
foo(Fun(a0), Fun(a1), Fun(a2) ...)

Ah, clever! I like it. I'd like to see this generalized a bit though. For instance, if the transform were instead "foo(_state, vararg<_>)" the intention is clear, but it doesn't sound like your implementation would handle this. Actually, the semantics get somewhat tricky. And I fear it would lead folks to believe that what gets unpacked by the vararg in the transform corresponds exactly to the children that were matched by the vararg in the grammar. That's not quite the case, is it?

How about this ... an "unpack" placeholder that works essentially how your vararg does, but with any Fusion sequence (including Proto expressions), and the sequence has to be explicitly specified (like the first parameter to proto::fold).

So, instead of foo(vararg<_>), you'd have foo(unpack(_)), where _ means "the sequence to unpack", not "the transform to apply to each element". If you want to apply a transform to each element first, you could specify the transform as a second parameter: foo(unpack(_, Fun)). (That form would probably use fusion::transform_view internally.)

The implementation of this would be very tricky, I think, because unpack could appear in any argument position,not just the first. And you'd have to be careful about compile times. But a fun little problem!

Additionally, you can add whatever arguments you like to the transform.

Which transform? Example?

Eric