| Home | Libraries | People | FAQ | More

#### Making Lazy Functions

If we limited ourselves to nothing but terminals and operator overloads, our embedded domain-specific languages wouldn't be very expressive. Imagine that we wanted to extend our calculator EDSL with a full suite of math functions like `sin()` and `pow()` that we could invoke lazily as follows.

    // A calculator expression that takes one argument
    // and takes the sine of it.
    sin(_1);

We would like the above to create an expression template representing a function invocation. When that expression is evaluated, it should cause the function to be invoked. (At least, that's the meaning of function invocation we'd like the calculator EDSL to have.) You can define `sin` quite simply as follows.

    // "sin" is a Proto terminal containing a function pointer
    proto::terminal< double(*)(double) >::type const sin = {&std::sin};

In the above, we define `sin` as a Proto terminal containing a pointer to the `std::sin()` function. Now we can use `sin` as a lazy function. The `default_context` that we saw in the Introduction knows how to evaluate lazy functions. Consider the following:

    double pi = 3.1415926535;
    proto::default_context ctx;
    // Create a lazy "sin" invocation and immediately evaluate it
    std::cout << proto::eval( sin(pi/2), ctx ) << std::endl;

The above code prints out:

    1

I'm no expert at trigonometry, but that looks right to me.

We can write `sin(pi/2)` because the `sin` object, which is a Proto terminal, has an overloaded `operator()()` that builds a node representing a function call invocation. The actual type of `sin(pi/2)` is actually something like this:

    // The type of the expression sin(pi/2):
    proto::function<
        proto::terminal< double(*)(double) >::type const &
        proto::result_of::as_child< double const >::type
    >::type

This type further expands to an unsightly node type with a tag type of `proto::tag::function` and two children: the first representing the function to be invoked, and the second representing the argument to the function. (Node tag types describe the operation that created the node. The difference between `a + b` and `a - b` is that the former has tag type `proto::tag::plus` and the latter has tag type `proto::tag::minus`. Tag types are pure compile-time information.)

| Note
In the type computation above, `proto::result_of::as_child<>` is a metafunction that ensures its argument is a Proto expression type. If it isn't one already, it becomes a Proto terminal. We'll learn more about this metafunction, along with `proto::as_child()`, its runtime counterpart, later. For now, you can forget about it.

It is important to note that there is nothing special about terminals that contain function pointers. Any Proto expression has an overloaded function call operator. Consider:

    // This compiles!
    proto::lit(1)(2)(3,4)(5,6,7,8);

That may look strange at first. It creates an integer terminal with `proto::lit()`, and then invokes it like a function again and again. What does it mean? Who knows?! You get to decide when you define an evaluation context or a transform. But more on that later.

###### Making Lazy Functions, Continued

Now, what if we wanted to add a `pow()` function to our calculator EDSL that users could invoke as follows?

    // A calculator expression that takes one argument
    // and raises it to the 2nd power
    pow< 2 >(_1);

The simple technique described above of making `pow` a terminal containing a function pointer doesn't work here. If `pow` is an object, then the expression `pow< 2 >(_1)` is not valid C++. (Well, technically it is; it means, `pow` less than 2, greater than `(_1)`, which is nothing at all like what we want.) `pow` should be a real function template. But it must be an unusual function: one that returns an expression template.

With `sin`, we relied on Proto to provide an overloaded `operator()()` to build an expression node with tag type `proto::tag::function` for us. Now we'll need to do so ourselves. As before, the node will have two children: the function to invoke and the function's argument.

With `sin`, the function to invoke was a raw function pointer wrapped in a Proto terminal. In the case of `pow`, we want it to be a terminal containing TR1-style function object. This will allow us to parameterize the function on the exponent. Below is the implementation of a simple TR1-style wrapper for the `std::pow` function:

    // Define a pow_fun function object
    template< int Exp >
    struct pow_fun
    {
        typedef double result_type;

        double operator()(double d) const
        {
            return std::pow(d, Exp);
        }
    };

Following the `sin` example, we want `pow< 1 >( pi/2 )` to have a type like this:

    // The type of the expression pow<1>(pi/2):
    proto::function<
        proto::terminal< pow_fun<1> >::type
        proto::result_of::as_child< double const >::type
    >::type

We could write a `pow()` function using code like this, but it's verbose and error prone; it's too easy to introduce subtle bugs by forgetting to call `proto::as_child()` where necessary, resulting in code that seems to work but sometimes doesn't. Proto provides a better way to construct expression nodes: `proto::make_expr()`.

###### Lazy Functions Made Simple With `make_expr()`

Proto provides a helper for building expression templates called `proto::make_expr()`. We can concisely define the `pow()` function with it as below.

    // Define a lazy pow() function for the calculator EDSL.
    // Can be used as: pow< 2 >(_1)
    template< int Exp, typename Arg >
    typename proto::result_of::make_expr<
        proto::tag::function  // Tag type
      , pow_fun< Exp >        // First child (by value)
      , Arg const &           // Second child (by reference)
    >::type const
    pow(Arg const &arg)
    {
        return proto::make_expr<proto::tag::function>(
            pow_fun<Exp>()    // First child (by value)
          , boost::ref(arg)   // Second child (by reference)
        );
    }

There are some things to notice about the above code. We use `proto::result_of::make_expr<>` to calculate the return type. The first template parameter is the tag type for the expression node we're building -- in this case, `proto::tag::function`.

Subsequent template parameters to `proto::result_of::make_expr<>` represent child nodes. If a child type is not already a Proto expression, it is automatically made into a terminal with `proto::as_child()`. A type such as `pow_fun<Exp>` results in terminal that is held by value, whereas a type like `Arg const &` (note the reference) indicates that the result should be held by reference.

In the function body is the runtime invocation of `proto::make_expr()`. It closely mirrors the return type calculation. `proto::make_expr()` requires you to specify the node's tag type as a template parameter. The arguments to the function become the node's children. When a child should be stored by value, nothing special needs to be done. When a child should be stored by reference, you must use the `boost::ref()` function to wrap the argument.

And that's it! `proto::make_expr()` is the lazy person's way to make a lazy funtion.