More on Actions

| Home | Libraries | People | FAQ | More

### More on Actions

As you know from the Actors in Detail section, Actions are what brings life to a Phoenix expression tree.

When dealing with a Phoenix expression tree, it gets evaluated top-down. Example:

    _1 + 3 * _2

Can be visualized as an AST in the following way:

In terms of actions this means:

- `rule::plus` is matched

- evaluate left:

  - `rule::placeholder` is matched

- evaluate right:

  - `rule::multiplies` is matched

    - evaluate left:

      - `rule::value` is matched

    - evaluate right:

      - `rule::placeholder` is matched

Every time a rule is matched, an action will be called. The action determines how the Phoenix AST will be traversed.

##### Writing an Action

As mentioned in Actors in Detail actions are Proto Primitive Transforms for convenience Phoenix provides an abstraction to this:

    template <typename Fun>
    struct call;

This is similar to `proto::call` but does more. It calls the `Fun` function object passed as template parameter with the `Context` and the children of the expression associated with the rule.

Lets have an (simplified) example on how to write an evaluation action for `rule::plus`:

    struct plus_eval
    {
        typedef int result_type;

        template <typename Lhs, typename Rhs, typename Context>
        result_type operator()(Lhs const& lhs, Rhs const &rhs, Context & ctx)
        {
            return eval(lhs, ctx) + eval(rhs, ctx);
        }
    };

    template <>
    struct default_actions::when<rule::plus>
        : call<plus_eval>
    {};

That's it. When evaluating a `plus` expression, the `plus_eval` callable gets called with the left hand side and right hand side expression and the associated Context.

But there is more: As Actions can be full fletched Proto Transforms, you can in fact use any proto expression you can imagine as the action. Phoenix predifines a set of callables and transform to deal with the Context information passed along and of course every Phoenix expression can be used as a Phoenix grammar or Proto Pass Through Transform.

`functional::context(Env, Actions)`

  A Proto Callable Transform that creates a new context out of the `Env` and `Actions` parameter

`functional::env(Context)`

  A Proto Callable Transform that returns the environment out of the `Context` parameter

`functional::actions(Context)`

  A Proto Callable Transform that returns the actions out of the `Context` parameter

`_context`

  A Proto Primitive Transform that returns the current context

`_env`

  A Proto Primitive Transform that returns the current environment

`_actions`

  A Proto Primitive Transform that returns the current actions

`context(env, actions)`

  A regular function that creates a context

`env(ctx)`

  A regular function that returns the environment from the given context

`actions(ctx)`

  A regular function that returns the actions from the given context

Phoenix is equipped with a predefined set of expressions, rules and actions to make all the stuff work you learned in the Starter Kit and Modules sections. See the next section for more details!