1<html> 2<head> 3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 4<title>lambda</title> 5<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css"> 6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1"> 7<link rel="home" href="../../../index.html" title="Chapter 1. Phoenix 3.2.0"> 8<link rel="up" href="../scope.html" title="Scope"> 9<link rel="prev" href="let.html" title="let"> 10<link rel="next" href="../bind.html" title="Bind"> 11</head> 12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> 13<table cellpadding="2" width="100%"><tr> 14<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td> 15<td align="center"><a href="../../../../../../../index.html">Home</a></td> 16<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td> 17<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> 18<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> 19<td align="center"><a href="../../../../../../../more/index.htm">More</a></td> 20</tr></table> 21<hr> 22<div class="spirit-nav"> 23<a accesskey="p" href="let.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../scope.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../bind.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a> 24</div> 25<div class="section"> 26<div class="titlepage"><div><div><h4 class="title"> 27<a name="phoenix.modules.scope.lambda"></a><a class="link" href="lambda.html" title="lambda">lambda</a> 28</h4></div></div></div> 29<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">scope</span><span class="special">/</span><span class="identifier">lambda</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> 30</pre> 31<p> 32 A lot of times, you'd want to write a lazy function that accepts one or 33 more functions (higher order functions). STL algorithms come to mind, for 34 example. Consider a lazy version of <code class="computeroutput"><span class="identifier">stl</span><span class="special">::</span><span class="identifier">for_each</span></code>: 35 </p> 36<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">for_each_impl</span> 37<span class="special">{</span> 38 <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">C</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">F</span><span class="special">></span> 39 <span class="keyword">struct</span> <span class="identifier">result</span> 40 <span class="special">{</span> 41 <span class="keyword">typedef</span> <span class="keyword">void</span> <span class="identifier">type</span><span class="special">;</span> 42 <span class="special">};</span> 43 44 <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">C</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">F</span><span class="special">></span> 45 <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">C</span><span class="special">&</span> <span class="identifier">c</span><span class="special">,</span> <span class="identifier">F</span> <span class="identifier">f</span><span class="special">)</span> <span class="keyword">const</span> 46 <span class="special">{</span> 47 <span class="identifier">std</span><span class="special">::</span><span class="identifier">for_each</span><span class="special">(</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span> <span class="identifier">f</span><span class="special">);</span> 48 <span class="special">}</span> 49<span class="special">};</span> 50 51<span class="identifier">function</span><span class="special"><</span><span class="identifier">for_each_impl</span><span class="special">></span> <span class="keyword">const</span> <span class="identifier">for_each</span> <span class="special">=</span> <span class="identifier">for_each_impl</span><span class="special">();</span> 52</pre> 53<p> 54 Notice that the function accepts another function, <code class="computeroutput"><span class="identifier">f</span></code> 55 as an argument. The scope of this function, <code class="computeroutput"><span class="identifier">f</span></code>, 56 is limited within the <code class="computeroutput"><span class="keyword">operator</span><span class="special">()</span></code>. When <code class="computeroutput"><span class="identifier">f</span></code> 57 is called inside <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">for_each</span></code>, it exists in a new scope, along 58 with new arguments and, possibly, local variables. This new scope is not 59 at all related to the outer scopes beyond the <code class="computeroutput"><span class="keyword">operator</span><span class="special">()</span></code>. 60 </p> 61<p> 62 Simple syntax: 63 </p> 64<pre class="programlisting"><span class="identifier">lambda</span> 65<span class="special">[</span> 66 <span class="identifier">lambda</span><span class="special">-</span><span class="identifier">body</span> 67<span class="special">]</span> 68</pre> 69<p> 70 Like <code class="computeroutput"><span class="identifier">let</span></code>, local variables 71 may be declared, allowing 1..N local variable declarations (where N == 72 <code class="computeroutput"><span class="identifier">BOOST_PHOENIX_LOCAL_LIMIT</span></code>): 73 </p> 74<pre class="programlisting"><span class="identifier">lambda</span><span class="special">(</span><span class="identifier">local</span><span class="special">-</span><span class="identifier">declarations</span><span class="special">)</span> 75<span class="special">[</span> 76 <span class="identifier">lambda</span><span class="special">-</span><span class="identifier">body</span> 77<span class="special">]</span> 78</pre> 79<p> 80 The same restrictions apply with regard to scope and visibility. The RHS 81 (right hand side lambda-expression) of each local-declaration cannot refer 82 to any LHS local-id. The local-ids are not in scope yet; they will be in 83 scope only in the lambda-body: 84 </p> 85<pre class="programlisting"><span class="identifier">lambda</span><span class="special">(</span> 86 <span class="identifier">_a</span> <span class="special">=</span> <span class="number">1</span> 87 <span class="special">,</span> <span class="identifier">_b</span> <span class="special">=</span> <span class="identifier">_a</span> <span class="comment">// Error: _a is not in scope yet</span> 88<span class="special">)</span> 89</pre> 90<p> 91 See <a class="link" href="let.html#phoenix.modules.scope.let.visibility"><code class="computeroutput"><span class="identifier">let</span></code> Visibility</a> for more information. 92 </p> 93<p> 94 Example: Using our lazy <code class="computeroutput"><span class="identifier">for_each</span></code> 95 let's print all the elements in a container: 96 </p> 97<pre class="programlisting"><span class="identifier">for_each</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">lambda</span><span class="special">[</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span><span class="special">])</span> 98</pre> 99<p> 100 As far as the arguments are concerned (arg1..argN), the scope in which 101 the lambda-body exists is totally new. The left <code class="computeroutput"><span class="identifier">arg1</span></code> 102 refers to the argument passed to <code class="computeroutput"><span class="identifier">for_each</span></code> 103 (a container). The right <code class="computeroutput"><span class="identifier">arg1</span></code> 104 refers to the argument passed by <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">for_each</span></code> 105 when we finally get to call <code class="computeroutput"><span class="keyword">operator</span><span class="special">()</span></code> in our <code class="computeroutput"><span class="identifier">for_each_impl</span></code> 106 above (a container element). 107 </p> 108<p> 109 Yet, we may wish to get information from outer scopes. While we do not 110 have access to arguments in outer scopes, what we still have is access 111 to local variables from outer scopes. We may only be able to pass argument 112 related information from outer <code class="computeroutput"><span class="identifier">lambda</span></code> 113 scopes through the local variables. 114 </p> 115<div class="note"><table border="0" summary="Note"> 116<tr> 117<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/src/images/note.png"></td> 118<th align="left">Note</th> 119</tr> 120<tr><td align="left" valign="top"><p> 121 This is a crucial difference between <code class="computeroutput"><span class="identifier">let</span></code> 122 and <code class="computeroutput"><span class="identifier">lambda</span></code>: <code class="computeroutput"><span class="identifier">let</span></code> does not introduce new arguments; 123 <code class="computeroutput"><span class="identifier">lambda</span></code> does. 124 </p></td></tr> 125</table></div> 126<p> 127 Another example: Using our lazy <code class="computeroutput"><span class="identifier">for_each</span></code>, 128 and a lazy <code class="computeroutput"><span class="identifier">push_back</span></code>: 129 </p> 130<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">push_back_impl</span> 131<span class="special">{</span> 132 <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">C</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span> 133 <span class="keyword">struct</span> <span class="identifier">result</span> 134 <span class="special">{</span> 135 <span class="keyword">typedef</span> <span class="keyword">void</span> <span class="identifier">type</span><span class="special">;</span> 136 <span class="special">};</span> 137 138 <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">C</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span> 139 <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">C</span><span class="special">&</span> <span class="identifier">c</span><span class="special">,</span> <span class="identifier">T</span><span class="special">&</span> <span class="identifier">x</span><span class="special">)</span> <span class="keyword">const</span> 140 <span class="special">{</span> 141 <span class="identifier">c</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span> 142 <span class="special">}</span> 143<span class="special">};</span> 144 145<span class="identifier">function</span><span class="special"><</span><span class="identifier">push_back_impl</span><span class="special">></span> <span class="keyword">const</span> <span class="identifier">push_back</span> <span class="special">=</span> <span class="identifier">push_back_impl</span><span class="special">();</span> 146</pre> 147<p> 148 write a lambda expression that accepts: 149 </p> 150<div class="orderedlist"><ol class="orderedlist" type="1"> 151<li class="listitem"> 152 a 2-dimensional container (e.g. <code class="computeroutput"><span class="identifier">vector</span><span class="special"><</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="special">></span></code>) 153 </li> 154<li class="listitem"> 155 a container element (e.g. <code class="computeroutput"><span class="keyword">int</span></code>) 156 </li> 157</ol></div> 158<p> 159 and pushes-back the element to each of the <code class="computeroutput"><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span></code>. 160 </p> 161<p> 162 Solution: 163 </p> 164<pre class="programlisting"><span class="identifier">for_each</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span> 165 <span class="identifier">lambda</span><span class="special">(</span><span class="identifier">_a</span> <span class="special">=</span> <span class="identifier">arg2</span><span class="special">)</span> 166 <span class="special">[</span> 167 <span class="identifier">push_back</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">_a</span><span class="special">)</span> 168 <span class="special">]</span> 169<span class="special">)</span> 170</pre> 171<p> 172 Since we do not have access to the arguments of the outer scopes beyond 173 the lambda-body, we introduce a local variable <code class="computeroutput"><span class="identifier">_a</span></code> 174 that captures the second outer argument: <code class="computeroutput"><span class="identifier">arg2</span></code>. 175 Hence: _a = arg2. This local variable is visible inside the lambda scope. 176 </p> 177<p> 178 (See <a href="../../../../../example/lambda.cpp" target="_top">lambda.cpp</a>) 179 </p> 180</div> 181<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> 182<td align="left"></td> 183<td align="right"><div class="copyright-footer">Copyright © 2002-2005, 2010, 2014, 2015 Joel de Guzman, Dan Marsden, Thomas 184 Heller, John Fletcher<p> 185 Distributed under the Boost Software License, Version 1.0. (See accompanying 186 file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) 187 </p> 188</div></td> 189</tr></table> 190<hr> 191<div class="spirit-nav"> 192<a accesskey="p" href="let.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../scope.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../bind.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a> 193</div> 194</body> 195</html> 196