lambda

| Home | Libraries | People | FAQ | More

#### lambda

    #include <boost/phoenix/scope/lambda.hpp>

A lot of times, you'd want to write a lazy function that accepts one or more functions (higher order functions). STL algorithms come to mind, for example. Consider a lazy version of `stl::for_each`:

    struct for_each_impl
    {
        template <typename C, typename F>
        struct result
        {
            typedef void type;
        };

        template <typename C, typename F>
        void operator()(C& c, F f) const
        {
            std::for_each(c.begin(), c.end(), f);
        }
    };

    function<for_each_impl> const for_each = for_each_impl();

Notice that the function accepts another function, `f` as an argument. The scope of this function, `f`, is limited within the `operator()`. When `f` is called inside `std::for_each`, it exists in a new scope, along with new arguments and, possibly, local variables. This new scope is not at all related to the outer scopes beyond the `operator()`.

Simple syntax:

    lambda
    [
        lambda-body
    ]

Like `let`, local variables may be declared, allowing 1..N local variable declarations (where N == `BOOST_PHOENIX_LOCAL_LIMIT`):

    lambda(local-declarations)
    [
        lambda-body
    ]

The same restrictions apply with regard to scope and visibility. The RHS (right hand side lambda-expression) of each local-declaration cannot refer to any LHS local-id. The local-ids are not in scope yet; they will be in scope only in the lambda-body:

    lambda(
        _a = 1
      , _b = _a // Error: _a is not in scope yet
    )

See `let` Visibility for more information.

Example: Using our lazy `for_each` let's print all the elements in a container:

    for_each(arg1, lambda[cout << arg1])

As far as the arguments are concerned (arg1..argN), the scope in which the lambda-body exists is totally new. The left `arg1` refers to the argument passed to `for_each` (a container). The right `arg1` refers to the argument passed by `std::for_each` when we finally get to call `operator()` in our `for_each_impl` above (a container element).

Yet, we may wish to get information from outer scopes. While we do not have access to arguments in outer scopes, what we still have is access to local variables from outer scopes. We may only be able to pass argument related information from outer `lambda` scopes through the local variables.

| Note
This is a crucial difference between `let` and `lambda`: `let` does not introduce new arguments; `lambda` does.

Another example: Using our lazy `for_each`, and a lazy `push_back`:

    struct push_back_impl
    {
        template <typename C, typename T>
        struct result
        {
            typedef void type;
        };

        template <typename C, typename T>
        void operator()(C& c, T& x) const
        {
            c.push_back(x);
        }
    };

    function<push_back_impl> const push_back = push_back_impl();

write a lambda expression that accepts:

1. a 2-dimensional container (e.g. `vector<vector<int> >`)
2. a container element (e.g. `int`)

and pushes-back the element to each of the `vector<int>`.

Solution:

    for_each(arg1,
        lambda(_a = arg2)
        [
            push_back(arg1, _a)
        ]
    )

Since we do not have access to the arguments of the outer scopes beyond the lambda-body, we introduce a local variable `_a` that captures the second outer argument: `arg2`. Hence: _a = arg2. This local variable is visible inside the lambda scope.

(See lambda.cpp)