Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext
Callable Transforms

In the grammar defined in the preceding section, the transform associated with non-terminals is a little strange-looking:

proto::when<
    _
  , LeftmostLeaf( proto::_child0 )   // <-- a "callable" transform
>

It has the effect of accepting non-terminal expressions, taking the 0th (leftmost) child and recursively invoking the LeftmostLeaf function on it. But LeftmostLeaf( proto::_child0 ) is actually a function type. Literally, it is the type of a function that accepts an object of type proto::_child0 and returns an object of type LeftmostLeaf. So how do we make sense of this transform? Clearly, there is no function that actually has this signature, nor would such a function be useful. The key is in understanding how proto::when<> interprets its second template parameter.

When the second template parameter to proto::when<> is a function type, proto::when<> interprets the function type as a transform. In this case, LeftmostLeaf is treated as the type of a function object to invoke, and proto::_child0 is treated as a transform. First, proto::_child0 is applied to the current expression (the non-terminal that matched this alternate sub-grammar), and the result (the 0th child) is passed as an argument to LeftmostLeaf.

[Note] Note

Transforms are a Domain-Specific Language

LeftmostLeaf( proto::_child0 ) looks like an invocation of the LeftmostLeaf function object, but it's not, but then it actually is! Why this confusing subterfuge? Function types give us a natural and concise syntax for composing more complicated transforms from simpler ones. The fact that the syntax is suggestive of a function invocation is on purpose. It is an embedded domain-specific language for defining expression transformations. If the subterfuge worked, it may have fooled you into thinking the transform is doing exactly what it actually does! And that's the point.

The type LeftmostLeaf( proto::_child0 ) is an example of a callable transform. It is a function type that represents a function object to call and its arguments. The types proto::_child0 and proto::_value are primitive transforms. They are plain structs, not unlike function objects, from which callable transforms can be composed. There is one other type of transform, object transforms, that we'll encounter next.


PrevUpHomeNext