1 [/==============================================================================
2 Copyright (C) 2001-2010 Joel de Guzman
3 Copyright (C) 2001-2005 Dan Marsden
4 Copyright (C) 2001-2010 Thomas Heller
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 ===============================================================================/]
12 Up until now, the most basic ingredient is missing: creation of and access to
13 local variables in the stack. When recursion comes into play, you will soon
14 realize the need to have true local variables. It may seem that we do not need
15 this at all since an unnamed lambda function cannot call itself anyway; at least
16 not directly. With some sort of arrangement, situations will arise where a
17 lambda function becomes recursive. A typical situation occurs when we store a
18 lambda function in a [@http://www.boost.org/libs/function Boost.Function],
19 essentially naming the unnamed lambda.
21 There will also be situations where a lambda function gets passed as an argument
22 to another function. This is a more common situation. In this case, the lambda
23 function assumes a new scope; new arguments and possibly new local variables.
25 This section deals with local variables and nested lambda scopes.
27 [section Local Variables]
29 #include <boost/phoenix/scope/local_variable.hpp>
31 We use an instance of:
33 expression::local_variable<Key>::type
35 to represent a local variable. The local variable acts as an imaginary data-bin
36 where a local, stack based data will be placed. `Key` is an arbitrary type that
37 is used to identify the local variable. Example:
40 expression::local_variable<size_key>::type size;
42 [*Predefined Local Variables]
44 There are a few predefined instances of `expression::local_variable<Key>::type`
45 named `_a`..`_z` that you can already use. To make use of them, simply use the
46 `namespace boost::phoenix::local_names`:
48 using namespace boost::phoenix::local_names;
53 #include <boost/phoenix/scope/let.hpp>
55 You declare local variables using the syntax:
57 let(local-declarations)
62 `let` allows 1..N local variable declarations (where N ==
63 `BOOST_PHOENIX_LOCAL_LIMIT`). Each declaration follows the form:
65 local-id = lambda-expression
67 [note You can set `BOOST_PHOENIX_LOCAL_LIMIT`, the predefined maximum local
68 variable declarations in a let expression. By default, `BOOST_PHOENIX_LOCAL_LIMIT` is
69 set to `BOOST_PHOENIX_LIMIT`.]
73 let(_a = 123, _b = 456)
78 [*Reference Preservation]
80 The type of the local variable assumes the type of the lambda- expression. Type
81 deduction is reference preserving. For example:
83 let(_a = arg1, _b = 456)
85 `_a` assumes the type of `arg1`: a reference to an argument, while `_b` has type
100 the output of above is : 0 0
116 Reference preservation is necessary because we need to have L-value access to
117 outer lambda-scopes (especially the arguments). `arg`s and `ref`s are L-values.
121 [#phoenix.modules.scope.let.visibility]
123 The scope and lifetimes of the local variables is limited within the let-body.
124 `let` blocks can be nested. A local variable may hide an outer local variable.
127 let(_x = _1, _y = _2)
129 // _x here is an int: 1
131 let(_x = _3) // hides the outer _x
133 cout << _x << _y // prints "Hello, World"
135 ](1," World","Hello,");
137 The actual values of the parameters _1, _2 and _3 are supplied from the
138 bracketed list at the end of the `let`.
140 There is currently a limitation that the inner `let` cannot be supplied with a
141 constant e.g. `let(_x = 1)`.
143 The RHS (right hand side lambda-expression) of each local-declaration cannot
144 refer to any LHS local-id. At this point, the local-ids are not in scope yet;
145 they will only be in scope in the let-body. The code below is in error:
149 , _b = _a // Error: _a is not in scope yet
152 // _a and _b's scope starts here
156 However, if an outer let scope is available, this will be searched. Since
157 the scope of the RHS of a local-declaration is the outer scope enclosing
158 the let, the RHS of a local-declaration can refer to a local variable of
165 , _b = _a // Ok. _a refers to the outer _a
175 #include <boost/phoenix/scope/lambda.hpp>
177 A lot of times, you'd want to write a lazy function that accepts one or more
178 functions (higher order functions). STL algorithms come to mind, for example.
179 Consider a lazy version of `stl::for_each`:
183 template <typename C, typename F>
189 template <typename C, typename F>
190 void operator()(C& c, F f) const
192 std::for_each(c.begin(), c.end(), f);
196 function<for_each_impl> const for_each = for_each_impl();
198 Notice that the function accepts another function, `f` as an argument. The scope
199 of this function, `f`, is limited within the `operator()`. When `f` is called
200 inside `std::for_each`, it exists in a new scope, along with new arguments and,
201 possibly, local variables. This new scope is not at all related to the outer
202 scopes beyond the `operator()`.
211 Like `let`, local variables may be declared, allowing 1..N local variable
212 declarations (where N == `BOOST_PHOENIX_LOCAL_LIMIT`):
214 lambda(local-declarations)
219 The same restrictions apply with regard to scope and visibility. The RHS
220 (right hand side lambda-expression) of each local-declaration cannot refer
221 to any LHS local-id. The local-ids are not in scope yet; they will be in
222 scope only in the lambda-body:
226 , _b = _a // Error: _a is not in scope yet
229 See [link phoenix.modules.scope.let.visibility `let` Visibility] for more information.
231 Example: Using our lazy `for_each` let's print all the elements in a container:
233 for_each(arg1, lambda[cout << arg1])
235 As far as the arguments are concerned (arg1..argN), the scope in which the
236 lambda-body exists is totally new. The left `arg1` refers to the argument passed
237 to `for_each` (a container). The right `arg1` refers to the argument passed by
238 `std::for_each` when we finally get to call `operator()` in our `for_each_impl`
239 above (a container element).
241 Yet, we may wish to get information from outer scopes. While we do not have
242 access to arguments in outer scopes, what we still have is access to local
243 variables from outer scopes. We may only be able to pass argument related
244 information from outer `lambda` scopes through the local variables.
246 [note This is a crucial difference between `let` and `lambda`: `let`
247 does not introduce new arguments; `lambda` does.]
249 Another example: Using our lazy `for_each`, and a lazy `push_back`:
251 struct push_back_impl
253 template <typename C, typename T>
259 template <typename C, typename T>
260 void operator()(C& c, T& x) const
266 function<push_back_impl> const push_back = push_back_impl();
268 write a lambda expression that accepts:
270 # a 2-dimensional container (e.g. `vector<vector<int> >`)
271 # a container element (e.g. `int`)
273 and pushes-back the element to each of the `vector<int>`.
284 Since we do not have access to the arguments of the outer scopes beyond the
285 lambda-body, we introduce a local variable `_a` that captures the second outer
286 argument: `arg2`. Hence: _a = arg2. This local variable is visible inside the
289 (See [@../../example/lambda.cpp lambda.cpp])