tutorial.qbk 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. [section Expressions]
  2. _yap_ consists of expressions and functions that operate on them. A function
  3. that takes an expression will accept any type that models the _Expr_ concept.
  4. For a type `T` to model the _Expr_ concept, `T` must contain at least an
  5. _kind_ (terminal, plus-operation, etc.) and a _tuple_ of values. That's it.
  6. [note The _tuple_ of values is constrained, based on the kind of the
  7. expression; see the full _Expr_ documentation for details.]
  8. Here's an example of an expression:
  9. [minimal_template]
  10. That's a template that models _ExprTmpl_. Instantiated with the proper
  11. template parameters, it produces _Exprs_.
  12. Ok, so it's not that interesting by itself _emdash_ `minimal_expr` has no
  13. operations defined for it. But we can still use it with the _yap_ functions
  14. that take an _Expr_. Let's make a _yap_ plus-expression manually:
  15. [minimal_template_manual_construction]
  16. If we evaluate it using _eval_, it does what you would expect:
  17. [minimal_template_evaluation]
  18. One more thing. It is important to remember that _yap_ expressions are
  19. all-lazy, all the time. There is no auto-evaluation of a _yap_ expression
  20. like there is with normal C++ expressions. If you want your expressions to be
  21. evaluated, you must call _eval_, or define non-lazy operations that force
  22. evaluation where and when you want it. This last approach is usually the
  23. right one, and there are lots of examples of how to do this in the _examples_
  24. section. In particular, checkout the _lazy_vector_ and _tarray_ examples.
  25. [endsect]
  26. [section Mix-and-Match Expression Templates]
  27. Because _yap_ operates on _Exprs_, it is possible to mix and match _Exprs_
  28. that are instantiations of different templates.
  29. Here's why that's important. Say we have two types in a library. `S` is a
  30. string type, and `M` is a matrix type. In the code here, `s` and `m` are
  31. objects of types `S` and `M` respectively. Say we also have typical operator
  32. overloads for these types, so `m * m` and `s[0]` are well-formed expressions,
  33. but `m[0]` and `s * s` are not.
  34. To use these with _yap_ I might write an expression template for each:
  35. template <...>
  36. struct m_expr
  37. {
  38. // ...
  39. };
  40. BOOST_YAP_USER_BINARY_OPERATOR(times, m_expr, m_expr)
  41. template <...>
  42. struct s_expr
  43. {
  44. // ...
  45. BOOST_YAP_USER_SUBSCRIPT_OPERATOR(::s_expr)
  46. };
  47. With this, I might write a _yap_ expression like:
  48. some_expr_producing_func(S("my_matrix")) * some_matrix
  49. I can transform this expression however I like, and do not have to worry about
  50. the fact that it contains expressions instantiated from different templates.
  51. If _yap_ required an expression to be instantiated from a single expression
  52. template `expr<>`, `expr<>` would have to have both operators. This means
  53. that all of a sudden `s * s` and `m[0]` would be well-formed expressions
  54. within a _yap_ expression, but *not* for the real types `S` and `M`
  55. respectively. That would be super weird.
  56. [endsect]
  57. [section Kinds of Expressions]
  58. Most of the expression kinds are the overloadable operators (`operator!()`,
  59. `operator<<=()`, etc.), See _kind_ for the full list.
  60. There are three special kinds of expressions:
  61. [variablelist
  62. [[_terminal_] [A terminal contains a non-Expression value, and represents a leaf-node in an
  63. expression tree. A terminal may have a _placeholder_ value, in which case it acts as a placeholder. ]]
  64. [[_if_else_] [An `if_else` expression is analogous to the C++ ternary operator (`?:`). It's up to you to make sure that the conditional expression given to `if_else` can be converted to `bool`; _yap_ does not check this.]]
  65. [[_expr_ref_] [An `expr_ref` expression is one that acts as a (possibly `const`) lvalue reference to another expression. It exists to prevent unnecessary copies of expressions.]]
  66. ]
  67. [endsect]
  68. [section Operators]
  69. Let's see an expression template type with some operators:
  70. [lazy_vector_decl]
  71. Those macros are used to define operator overloads that return _Exprs_. As
  72. shown here, that sort of operator can be mixed with normal, non-lazy ones
  73. _emdash_ the `operator[]` is a normal eager function.
  74. Use of the macros is not necessary (you can write your own operators that
  75. return _Exprs_ if you like), but it is suitable 99% of the time.
  76. Making the operators easy to define like this allows you to define custom
  77. expression templates that have only the operators defined that are appropriate
  78. for your use case.
  79. Detailed documentation on all the available macros can be found later in the
  80. _operator_macros_ section.
  81. [endsect]
  82. [section Transforming Expressions]
  83. Transformations in _yap_ are done using the _xform_ function.
  84. Let's take another look at the example expression from the intro:
  85. [$yap/img/expr.png]
  86. Consider a call to _xform_, operating on that expression:
  87. auto result = boost::yap::transform(expr, xform);
  88. _yap_'s _xform_ first looks at the top level expression, which in this case is
  89. a `+` expression. If the transform object `xform` matches the `+` expression,
  90. _xform_ is done; it just returns `xform(expr)`. If `xform` does not match the
  91. `+` expression, _xform_ transforms all its operands (which for `operator+()`
  92. is just the left and right operands), and returns a new `+` expression with
  93. those transformed operands. What I mean by "match" is covered in detail
  94. below.
  95. The overall effect of this is that _xform_ effectively copies an `expr` node
  96. that *does not* match `xform`, and returns a transformed node for an `expr`
  97. node that *does* match `xform`.
  98. _xform_ can also take multiple transform objects. If you call it with N
  99. transform objects, it will attempt to match each of the N transforms to a
  100. given expression, one at a time and in their given order. Only if no
  101. transform matches an expression does the copy-and-recurse behavior kick in.
  102. [note There's another form of _xform_, _xform_strict_. _xform_strict_ is
  103. identical to _xform_ except that it does not copy or recurse into an unmatched
  104. expression. Instead, a failed match is a hard error. This is useful when you
  105. have written a transform that you expect to completely transform an
  106. expression, and you want the compiler to tell you if you've made a mistake.]
  107. One common result of calling _xform_ is that you create a copy of `expr`, with
  108. a few matching nodes transformed. But this does not have to be the result of
  109. calling _xform_, because a _yap_ transformation is free-form; it must return a
  110. value, but may do just about anything else. It can transform an expression
  111. into anything _emdash_ a new expression of any kind, or even a non-expression
  112. value (effectively evaluating the expression). As before, here is the
  113. `get_arity` transform from the _calc3_ example. It returns a value, not an
  114. _Expr_:
  115. [calc3_get_arity_xform]
  116. Also, note that in this case the transform is stateless, but you could also
  117. give your transform objects data members containing contextual state:
  118. [vector_take_nth_xform]
  119. [tip Often when you create an expression, you will want to evaluate it in
  120. different contexts, changing its evaluation _emdash_ or even entire meaning
  121. _emdash_ in each context. _eval_ is wrong for this task, since it only takes
  122. values for substitution into placeholders. In these situations, you should
  123. instead use multiple transforms that evaluate your expression in different
  124. ways.]
  125. [heading When _xform_ Recurses]
  126. As described above, _xform_ only recurses when it *does not* find a match.
  127. This means that if you want to transform a nonterminal, say an
  128. `expr_kind::call` expression we'll call `C`, and *also* `C`'s subexpressions,
  129. you must explicitly call _xform_ yourself in your transform that matches `C`.
  130. You can see this kind of explicit _xform_ call in the recursive case of
  131. `get_arity` in the example code above.
  132. [note The code you write with _yap_ is likely going to be very generic,
  133. especially when you're writing a transform. _xform_ requires an _Expr_ as its
  134. first parameter. In situations when you want to make sure that the first
  135. parameter you pass to _xform_ is always a _yap_ expression, use the _as_expr_
  136. function. This is commonly needed when writing a transform in which you
  137. manually recurse by calling _xform_ inside one of your transform overloads.]
  138. [heading Transform Matching]
  139. In _yap_ a _XForm_ is a _Callable_ that has *zero or more* overloads that
  140. model the _ExprXForm_ or _TagXForm_ concepts.
  141. An _ExprXForm_ overload takes a single parameter whose type is the expression
  142. to be transformed. Here's one from a transform object in the _future_group_
  143. example:
  144. [expr_xform]
  145. _ExprXForms_ are most useful when you want to transform a narrow set of
  146. expression types (perhaps only one). In particular, you can distinguish
  147. between `const` and non-`const`, reference and non-reference, etc., in the
  148. expression and its operands in a way that you have less control over with the
  149. other kind of transform.
  150. A _TagXForm_ overload takes a tag that indicates the _kind_ of the expression
  151. to be transformed, and then (loosely) the value of each operand of the
  152. expression to be transformed. This looseness prevents you from needing to
  153. write out the full type of the matched expression. Here's one from the
  154. _pipable_algorithms_ example:
  155. [tag_xform]
  156. _TagXForms_ are most useful when the transform needs to match an expression
  157. without regard to whether its operands are _expr_ref_ expressions, or _emdash_
  158. if they are terminals _emdash_ whether they contain or refer to their values.
  159. _TagXForms_ tend to be far more concise.
  160. [heading A More Rigorous Description of TagTransform Parameters]
  161. That "(loosely)" before probably bothered you, right? Me too. Each non-tag
  162. parameter is passed to a _TagXForm_ by calling an operand accessor appropriate
  163. to `expr`'s kind, and then calling a terminal-specific version of _value_
  164. (`terminal_value()`) on the result. For example, consider a plus expression
  165. `expr`. The _TagXForm_ on a transform object `xform` would be called like
  166. this:
  167. xform(plus_tag, terminal_value(left(expr)), terminal_value(right(expr)))
  168. The operand accessors (_left_ and _right_ in this example) all dereference
  169. _expr_ref_ expressions before operating on them, and `terminal_value()` does
  170. the same.
  171. `terminal_value()` works much like _value_, except that it does not take the
  172. value of a *nonterminal* unary expression; it just forwards a nonterminal
  173. through. It still takes values out of terminals and unwraps _expr_ref_
  174. expressions, though.
  175. The auto-unwrapping of terminals means that you can effectively ignore the
  176. presence of _expr_ref_ expressions when writing a _TagXForm_. You can also
  177. just deal with the values inside terminals, and not the terminals
  178. themselves. Also, you can match all terminal value qualifiers (`const` or not,
  179. lvalue or rvalue) uniformly with a `T const &` parameter. Finally, you can
  180. write _TagXForm_ parameter types that can catch conversions; for instance, you
  181. can match any negation expression containing a terminal, *or a reference to
  182. one*, containing a value convertible to `double` like this:
  183. struct xform
  184. {
  185. auto operator() (boost::yap::negate_tag, double x)
  186. { return /* ... */; }
  187. }
  188. That will match a negation of a terminal containing an `unsigned int`,
  189. `unsigned int &`, `int const &`, `float &&`, etc. It will also match a
  190. negation of a reference to such a terminal.
  191. [heading Mixing the Two Kinds of Transforms]
  192. You can have two overloads in your transform that match an expression, one an
  193. _ExprXForm_ and one a _TagXForm_, and there will not be any ambiguity. The
  194. _TagXForm_ is matched first, and the _ExprXForm_ is matched only if the
  195. _TagXForm_ did not. You don't have to worry about ambiguity, but save
  196. yourself some confusion and mix the two kinds of overloads as little as
  197. possible.
  198. [note The above only applies when you have an _ExprXForm_ and a _TagXForm_
  199. that match *the same kind of expression*. Having unrelated _ExprXForms_ and
  200. _TagXForms_ within the same transform object is often quite useful.]
  201. [heading Multiple Transform Objects]
  202. In the case that multiple transform objects are being used in _xform_, the
  203. above logic applies to each one independently before the next one is used. In
  204. other words, in the call `boost::yap::transform(expr, a, b)`, _xform_ tries to
  205. match any _TagXForm_ from `a` to an expression first, then any _ExprXForm_
  206. from `a`, then any _TagXForm_ from `b`, and finally any _ExprXForm_ from `b`.
  207. [heading YAP-Supplied Transforms]
  208. _yap_ comes with a couple of functions that return ready-made transforms,
  209. _replacements_ and _evaluation_.
  210. The transforms returned by _replacements_ replace only placeholder terminals.
  211. Placeholder `I` is replaced by the `I-1`-th argument passed to _replacements_.
  212. Placeholders are `1`-based for consistency with other Boost and `std`
  213. placeholders.
  214. There are also a couple of specialty transform functions,
  215. _replace_placeholders_ and _eval_. These are convenience functions that just
  216. call _xform_ on an expression using _replacements_ or _evaluation_ as the
  217. transform, respectively.
  218. The behavior of _evaluation_ is covered in the next section, [link
  219. boost_yap.manual.evaluating_expressions Evaluating Expressions].
  220. [endsect]
  221. [section Evaluating Expressions]
  222. _yap_ expressions are evaluated explicitly, by calling the _eval_ function or
  223. calling _xform_ using a transform object returned from _evaluation_. The
  224. former is a convenince function that does the latter.
  225. _eval_ simply removes all the _yap_ machinery from an expression and evaluates
  226. it exactly as it would have been if _yap_ were not used. This means that
  227. functions are called, operators evaluated, etc. all as normal. To illustrate
  228. this, take a look at the implementation of `operator,()` used in _eval_:
  229. [evaluation_transform_comma]
  230. What this transformation does is transform the left and right expressions, and
  231. then use the built-in `operator,()` on the result. The evaluation
  232. transformations for the other operators do the same thing _emdash_ evaluate
  233. the operands, then return the result of applying the built-in operator to the
  234. operands.
  235. Function calls are done in a similar way, except that the callable is also a
  236. subexpression that needs to be evaluated before being called:
  237. [evaluation_transform_call]
  238. [endsect]
  239. [section Operator Macros]
  240. If you got here without reading the _operators_ section, go read that first.
  241. Here are the operator macros and their uses:
  242. [table Unary and Binary Operator-Defining Macros
  243. [[Macro] [Use] [First/Left Operand Type] [Right Operand Type] [Notes]]
  244. [[_unary_m_] [Unary operators.] [An _Expr_ instantiated from _ExprTmpl_ macro parameter `expr_template`.] [--] []]
  245. [[_binary_m_] [Binary operators.] [Any type.] [Any type.] [At least one parameter must be an _Expr_ instantiated from _ExprTmpl_ macro parameter `expr_template`.]]
  246. [[_udt_unary_m_] [Free operators defined over non-_Expr_ types constrained by a type trait (e.g. all `std::map<>`s).] [Any non-_Expr_ that satisfies the given type trait.] [--] []]
  247. [[_udt_udt_binary_m_] [Free operators defined over non-_Expr_ types constrained by a pair of type traits (e.g. a `std::map<>` on the left, and a `std::vector<>` on the right). Useful for type-asymmetric operators.] [Any non-_Expr_ that satisfies the left-hand type trait.] [Any non-_Expr_ that satisfies the right-hand type trait.] []]
  248. [[_udt_any_binary_m_] [Free operators defined over pairs of non-_Expr_ types, one constrained by a type trait and one not (e.g. a `std::list<>` on either side, and anything on the other).] [Any non-_Expr_.] [--] [At least one parameter must satisfy the given type trait.]]
  249. ]
  250. Some operators may only be defined as member functions, and so are not covered
  251. by general-purpose the unary and binary operator macros above:
  252. [table The Member-Only Operator Macros
  253. [[Macro] [Use] [Operands] [Notes]]
  254. [[_member_assign_m_] [Assignment operator.] [Any type except `decltype(*this)`.] [Does not conflict with the assignment or move assignment operators.]]
  255. [[_member_subscript_m_] [Subscript operator.] [Any type.] []]
  256. [[_member_call_m_] [Call operator taking any number of parameters.] [Any type.] []]
  257. [[_member_call_n_m_] [Call operator taking exactly N parameters.] [Any type.] []]
  258. ]
  259. [table if_else Psuedo-Operator Macros
  260. [[Macro] [Use] [Operands] [Notes]]
  261. [[_expr_if_else_m_] [Free `if_else()` function that requires at least one parameter to be an expression.] [Any type.] [At least one parameter must be an _Expr_.]]
  262. [[_udt_any_if_else_m_] [Free `if_else()` function for non-_Expr_ types that requires at least one parameter to satisfy the given type trait.] [Any non-_Expr_.] [At least one parameter must satisfy the given type trait.]]
  263. ]
  264. [note Operands are handled in a uniform way across all functions defined by
  265. all the macros listed here. See _how_treated_ for details.]
  266. [endsect]
  267. [section How Expression Operands Are Treated]
  268. For any _expr_ operator overload, or any function defined using one of the
  269. function definition macros, operands are treated in a uniform way.
  270. The guiding design principle here is that an expression built using _yap_
  271. should match the semantics of a builtin C++ expression as closely as possible.
  272. This implies that an rvalue be treated as if it were a temporary (as it may in
  273. fact have initially been) throughout the building and transformation of an
  274. expression, and that an lvalue should retain its connection to the underlying
  275. named entity to which it refers.
  276. For example, if you see
  277. auto expr = a + 1;
  278. you should expect that `a` will be an lvalue reference to some object of type
  279. `decltype(a)`, regardless of whether `a` is a _yap_ _Expr_ or a builtin type.
  280. Similarly, you should expect the `1` to be an rvalue, whether wrapped in a
  281. terminal or not.
  282. Let's take a quick look at _make_term_. If you call it with a `T` rvalue, the
  283. terminal's value type is a `T`, and the rvalue gets moved into it. If you
  284. call it with a `T [const]` lvalue, the value type is `T [const] &`, and the
  285. reference refers to the lvalue (read `[const]` as "possibly
  286. `const`-qualified"). This is important because you might write through the
  287. terminal later in an assignment operation. You don't want to lose the ability
  288. to do this, or be forced to write some Baroque pile of code to do so _emdash_
  289. it should be natural and easy.
  290. And it is:
  291. [assign_through_terminal]
  292. Now, there is a wrinkle. _yap_'s lazy expressions can be built piecemeal:
  293. auto subexpr = boost::yap::make_terminal(1) + 2;
  294. // This is fine, and acts more-or-less as if you wrote "1 / (1 + 2)".
  295. auto expr = 1 / subexpr;
  296. whereas C++'s eager builtin expressions cannot:
  297. auto subexpr = 1 + 2; // Same as "int subexpr = 3;". Hm.
  298. auto expr = 1 / subexpr; // Same as "int expr = 0;" Arg.
  299. Ok, so since you can build these lazy _yap_ expressions up from
  300. subexpressions, how do we treat the subexpressions? We treat them in exactly
  301. the same way as _make_term_ treats its parameter. Rvalues are moved in, and
  302. lvalues are captured by (possibly `const`) reference.
  303. [note If you want to subvert the capture-by-reference semantics of using
  304. subexpressions, just `std::move()` them. That will force a move _emdash_ or
  305. copy of values for which move is not defined.]
  306. The capture-by-reference behavior is implemented via a special _kind_,
  307. _expr_ref_. An `expr_ref` expression has a single data element: a (possibly
  308. `const` (Can I stop saying that every time? You get it, right? Ok, good.))
  309. reference to an expression. This additional level of indirection causes some
  310. complications at times, as you can see in the examples. Fortunately, the
  311. complications are not overly cumbersome.
  312. So, given the rules above, here is a comprehensive breakdown of what happens
  313. when an operand is passed to a _yap_ operator. In this table, `expr_tmpl` is
  314. an _ExprTmpl_, and `T` is a non-_Expr_ type. `E` refers to any non-`expr_ref`
  315. _Expr_. _yap_ does a partial decay on non-_Expr_ operands, in which `cv` and
  316. reference qualifiers are left unchanged, but arrays are decayed to pointers
  317. and functions are decayed to function pointers. `PARTIAL_DECAY(T)` indicates
  318. such a partial decay of `T`.
  319. [table Operand Handling
  320. [[Operand] [Captured As] [Notes]]
  321. [[`T const &`] [`expr_tmpl<expr_kind::terminal, boost::hana::tuple<PARTIAL_DECAY(T)>>`] []]
  322. [[`T &`] [`expr_tmpl<expr_kind::terminal, boost::hana::tuple<PARTIAL_DECAY(T)>>`] []]
  323. [[`T &&`] [`expr_tmpl<expr_kind::terminal, boost::hana::tuple<PARTIAL_DECAY(T)>>`] [Operand moved.]]
  324. [[`E const &`] [`expr_tmpl<expr_kind::expr_ref, boost::hana::tuple<E const &>>`] []]
  325. [[`E &`] [`expr_tmpl<expr_kind::expr_ref, boost::hana::tuple<E &>>`] []]
  326. [[`E &&`] [`E`] [Operand moved.]]
  327. [[`expr_tmpl<expr_kind::expr_ref, ...> const &`] [`expr_tmpl<expr_kind::expr_ref, ...>`] []]
  328. [[`expr_tmpl<expr_kind::expr_ref, ...> &`] [`expr_tmpl<expr_kind::expr_ref, ...>`] []]
  329. [[`expr_tmpl<expr_kind::expr_ref, ...> &&`] [`expr_tmpl<expr_kind::expr_ref, ...>`] [Operand moved.]]
  330. ]
  331. The partial decay of non-_Expr_ operands is another example of how _yap_
  332. attempts to create expression trees that are as semantically close to builtin
  333. expressions as possible.
  334. [endsect]
  335. [section Printing]
  336. _yap_ has a convenient _print_ function, that prints an expression tree to a
  337. stream. It is not intended for production work (for instance, it has no
  338. formatting options), but it is excellent for debugging and instrumentation.
  339. Since it is only a debugging aid, _print_ is found in a separate header not
  340. included when you include _yap_ with
  341. #include <boost/yap/yap.hpp>
  342. You must include `<boost/yap/print.hpp>` explicitly.
  343. _print_ handles several patterns of expression specially, to allow a concise
  344. representation of a given expression tree. For example, given this
  345. definition:
  346. [print_decl]
  347. and this expression:
  348. [print_expr]
  349. _print_ produces this output:
  350. [pre
  351. expr<->
  352. expr<+>
  353. term<boost::yap::placeholder<4ll>>[=4\]
  354. expr<*>
  355. term<double &>[=1\]
  356. term<thing>[=<<unprintable-value>>\] &
  357. term<char const*>[=lvalue terminal\] const &
  358. ]
  359. As you can see, _print_ shows one node per line, and represents the tree
  360. structure with indentation. It abbreviates non-terminal nodes in the tree
  361. `expr<op>`, where `op` is an operator symbol. Terminal nodes are abbreviated
  362. `term<T>`, where `T` is the type of value contained in the terminal; this may
  363. be a reference type or a value.
  364. A `term` node may not be a terminal node at all, but an _expr_ref_ expression
  365. containing a terminal. Such a _expr_ref_ node has a `&` or `const &` suffix,
  366. to indicate that it is a mutable or `const` reference, respectively.
  367. Each `term` node has a bracketed value near the end. The format is `[=X]`
  368. where `X` is the value the terminal contains. If the terminal contains a
  369. value for which no `operator<<(std::ostream &, ...)` overload exists (such as
  370. the `thing` type above), `X` will be `<<unprintable-value>>`.
  371. [endsect]