]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 Lazy Operators] | |
11 | ||
12 | You can use the usual set of operators to form expressions. Examples: | |
13 | ||
14 | arg1 * arg1 | |
15 | ref(x) = arg1 + ref(z) | |
16 | arg1 = arg2 + (3 * arg3) | |
17 | ref(x) = arg1[arg2] // assuming arg1 is indexable and arg2 is a valid index | |
18 | ||
19 | Note the expression: `3 * arg3`. This expression is actually a short-hand | |
20 | equivalent to: `val(3) * arg3`. In most cases, like above, you can get away with | |
21 | it. But in some cases, you will have to explicitly wrap your values in `val`. | |
22 | Rules of thumb: | |
23 | ||
24 | * In a binary expression (e.g. `3 * arg3`), at least one of the operands must be | |
25 | a phoenix primitive or expression. | |
26 | * In a unary expression (e.g. `arg1++`), the single operand must be a phoenix | |
27 | primitive or expression. | |
28 | ||
29 | If these basic rules are not followed, the result is either an error, or is | |
30 | immediately evaluated. Some examples: | |
31 | ||
32 | ref(x) = 123 // lazy | |
33 | x = 123 // immediate | |
34 | ||
35 | ref(x)[0] // lazy | |
36 | x[0] // immediate | |
37 | ||
38 | ref(x)[ref(i)] // lazy | |
39 | ref(x)[i] // lazy (equivalent to ref(x)[val(i)]) | |
40 | x[ref(i)] // illegal (x is not a phoenix primitive or expression) | |
41 | ref(x[ref(i)]) // illegal (x is not a phoenix primitive or expression) | |
42 | ||
43 | Why are the last two expression illegal? Although `operator[]` looks as | |
44 | much like a binary operator as `operator=` above it; the difference is | |
45 | that the former must be a member (i.e. `x` must have an `operator[]` | |
46 | that takes a phoenix primitive or expression as its argument). This will | |
47 | most likely not be the case. | |
48 | ||
49 | [blurb __tip__ Learn more about operators [link phoenix.modules.operator here.]] | |
50 | ||
51 | [heading First Practical Example] | |
52 | ||
53 | We've covered enough ground to present a real world example. We want to find the | |
54 | first odd number in an STL container. Normally we use a functor (function | |
55 | object) or a function pointer and pass that in to STL's `find_if` generic | |
56 | function: | |
57 | ||
58 | Write a function: | |
59 | ||
60 | bool | |
61 | is_odd(int arg1) | |
62 | { | |
63 | return arg1 % 2 == 1; | |
64 | } | |
65 | ||
66 | Pass a pointer to the function to STL's `find_if` algorithm: | |
67 | ||
68 | std::find_if(c.begin(), c.end(), &is_odd) | |
69 | ||
70 | Using Phoenix, the same can be achieved directly with a one-liner: | |
71 | ||
72 | std::find_if(c.begin(), c.end(), arg1 % 2 == 1) | |
73 | ||
74 | The expression `arg1 % 2 == 1` automagically creates a functor with the expected | |
75 | behavior. In FP, this unnamed function is called a lambda function. Unlike the | |
76 | function pointer version, which is monomorphic (expects and works only with a | |
77 | fixed type int argument), the Phoenix version is fully polymorphic and works | |
78 | with any container (of ints, of longs, of bignum, etc.) as long as its elements | |
79 | can handle the `arg1 % 2 == 1` expression. | |
80 | ||
81 | (See [@../../example/find_if.cpp find_if.cpp]) | |
82 | ||
83 | [blurb __tip__ ...[*That's it, we're done]. Well if you wish to know a little bit | |
84 | more, read on...] | |
85 | ||
86 | [endsect] | |
87 |