1[/============================================================================== 2 Copyright (C) 2001-2010 Joel de Guzman 3 Copyright (C) 2001-2005 Dan Marsden 4 Copyright (C) 2001-2010 Thomas Heller 5 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===============================================================================/] 9 10[section Core] 11 12Actors are composed to create more complex actors in a tree-like hierarchy. The 13primitives are atomic entities that are like the leaves in the tree. Phoenix is 14extensible. New primitives can be added anytime. Right out of the box, there are 15only a few primitives, these are all defined in the Core module. 16 17This section shall deal with these preset primitives. 18 19[section Values] 20 21 22 #include <boost/phoenix/core/value.hpp> 23 24Whenever we see a constant in a partially applied function, an 25 26 expression::value<T>::type 27 28(where T is the type of the constant) is automatically created for 29us. For instance: 30 31 add(arg1, 6) 32 33Passing a second argument, `6`, an `expression::value<T>::type` is implicitly created 34behind the scenes. This is also equivalent to `add(arg1, val(6))`. 35 36 val(v) 37 38generates an `expression::value<T>::type` where `T` is the type of `v`. In most 39cases, there's no need to explicitly use `val`, but, as we'll see later on, 40there are situations where this is unavoidable. 41 42[h2 Evaluating a Value] 43 44Like arguments, values are also actors. As such, values can be evaluated. 45Invoking a value gives the value's identity. Example: 46 47 cout << val(3)() << val("Hello World")(); 48 49prints out "3 Hello World". 50 51[endsect] 52 53[section References] 54 55 #include <boost/phoenix/core/reference.hpp> 56 57Values are immutable constants. Attempting to modify a value will result in a 58compile time error. When we want the function to modify the parameter, we use a 59reference instead. For instance, imagine a lazy function `add_assign`: 60 61 void add_assign(T& x, T y) { x += y; } // pseudo code 62 63Here, we want the first function argument, x, to be mutable. Obviously, we 64cannot write: 65 66 add_assign(1, 2) // error first argument is immutable 67 68In C++, we can pass in a reference to a variable as the first argument in our 69example above. Yet, by default, the library forces arguments passed to partially 70applied functions to be immutable values (see [link phoenix.modules.core.values 71Values]). To achieve our intent, we use: 72 73 expression::reference<T>::type 74 75This is similar to `expression::value<T>::type` before but instead holds a reference to a 76variable. 77 78We normally don't instantiate `expression::reference<T>::type` objects directly. Instead we 79use: 80 81 ref(v) 82 83For example (where `i` is an `int` variable): 84 85 add_assign(ref(i), 2) 86 87[heading Evaluating a Reference] 88 89References are actors. Hence, references can be evaluated. Such invocation gives 90the reference's identity. Example: 91 92 int i = 3; 93 char const* s = "Hello World"; 94 cout << ref(i)() << ref(s)(); 95 96prints out "3 Hello World" 97 98 99[heading Constant References] 100 101Another free function 102 103 cref(cv) 104 105may also be used. `cref(cv)` creates an 106`expression::reference<T const>::type` object. This is similar to `expression::value<T>::type` but 107when the data to be passed as argument to a function is heavy and expensive to 108copy by value, the `cref(cv)` offers a lighter alternative. 109 110[endsect] 111 112[section Arguments] 113 114 #include <boost/phoenix/core/argument.hpp> 115 116We use an instance of: 117 118 expression::argument<N>::type 119 120to represent the Nth function argument. The argument placeholder acts as an 121imaginary data-bin where a function argument will be placed. 122 123[heading Predefined Arguments] 124 125There are a few predefined instances of `expression::argument<N>::type` named 126`arg1`..`argN`, and its __bll__ counterpart `_1`..`_N`. (where N is a predefined 127maximum). 128 129Here are some sample preset definitions of `arg1`..`argN` 130 131 namespace placeholders 132 { 133 expression::argument<1>::type const arg1 = {}; 134 expression::argument<2>::type const arg2 = {}; 135 expression::argument<3>::type const arg3 = {}; 136 } 137 138and its __bll__ `_1`..`_N` style counterparts: 139 140 141 namespace placeholders 142 { 143 expression::argument<1>::type const _1 = {}; 144 expression::argument<2>::type const _2 = {}; 145 expression::argument<3>::type const _3 = {}; 146 } 147 148[note You can set `BOOST_PHOENIX_ARG_LIMIT`, the predefined maximum 149placeholder index. By default, `BOOST_PHOENIX_ARG_LIMIT` is set to `BOOST_PHOENIX_LIMIT` 150(See [link phoenix.actor Actor]).] 151 152[heading User Defined Arguments] 153 154When appropriate, you can define your own `argument` names. For example: 155 156 expression::argument<1>::type x; // note one based index 157 158`x` may now be used as a parameter to a lazy function: 159 160 add(x, 6) 161 162which is equivalent to: 163 164 add(arg1, 6) 165 166[/note 167When dealing with argument placeholders the question arises whether you can call 168member functions on an `argument` actor. 169 170This is possible by supplying a custom `actor` which has a member 171generator function. See [link phoenix.advanced_topics.extending_actors Extending Actors] 172for more details. 173] 174 175[heading Evaluating an Argument] 176 177An argument, when evaluated, selects the Nth argument from the those passed 178in by the client. 179 180For example: 181 182 char c = 'A'; 183 int i = 123; 184 const char* s = "Hello World"; 185 186 cout << arg1(c) << endl; // Get the 1st argument: c 187 cout << arg1(i, s) << endl; // Get the 1st argument: i 188 cout << arg2(i, s) << endl; // Get the 2nd argument: s 189 190will print out: 191 192 A 193 123 194 Hello World 195 196[heading Extra Arguments] 197 198In C and C++, a function can have extra arguments that are not at all used by 199the function body itself. These extra arguments are simply ignored. 200 201Phoenix also allows extra arguments to be passed. For example, recall our 202original `add` function: 203 204 add(arg1, arg2) 205 206We know now that partially applying this function results to a function that 207expects 2 arguments. However, the library is a bit more lenient and allows the 208caller to supply more arguments than is actually required. Thus, `add` actually 209allows 2 /or more/ arguments. For instance, with: 210 211 add(arg1, arg2)(x, y, z) 212 213the third argument `z` is ignored. Taking this further, in-between arguments are 214also ignored. Example: 215 216 add(arg1, arg5)(a, b, c, d, e) 217 218Here, arguments b, c, and d are ignored. The function `add` takes in the first 219argument (`arg1`) and the fifth argument (`arg5`). 220 221[note There are a few reasons why enforcing strict arity is not 222desirable. A case in point is the callback function. Typical callback functions 223provide more information than is actually needed. Lambda functions are often 224used as callbacks.] 225 226[endsect] 227 228[section Nothing] 229 230 #include <boost/phoenix/core/nothing.hpp> 231 232Finally, the `expression::null<mpl::void_>::type` does nothing; (a "bum", if you will :-) ). 233There's a sole `expression::null<mpl::void_>::type` instance named "nothing". This actor is 234actually useful in situations where we don't want to do anything. (See 235[link phoenix.modules.statement.for_statement for_ Statement] for example). 236 237[endsect] 238 239[endsect] 240