2
0
mirror of https://github.com/boostorg/yap.git synced 2026-02-23 16:22:09 +00:00
Files
yap/doc/examples.qbk
2016-12-13 17:06:26 -06:00

199 lines
5.2 KiB
Plaintext

[section Examples]
Most of these examples are patterned after the examples from Boost.Proto. In
part, this was done to underscore where _yap_ can do what Proto can, and where
it cannot.
Where possible, a Proto-derived example uses syntax in `main()` identical to
that in the original Proto example.
[section Hello World]
Welp. Remember how I mentioned earlier that _yap_ does things in a completely
lazy way? There's no easy way to get the same line of code that you saw in
`main()` in the Proto version of this example, because _yap_ doesn't know that
it should evaluate your expression eagerly in this case. It can be done, but
it's a bit of code. This is one case in which Proto's eager evaluation can
prove easier to use than _yap_'s lazy evaluation.
[hello_world]
[endsect]
[section Hello World Redux]
That's better! Sort of.... We created a custom expression template with an
eager stream operator. This gives us eager evaluation, but gives away all the
lazy AST building-then-evaluating that we're using _ets_ for in the first
place. In this simple example, we don't really need it.
[hello_world_redux]
[endsect]
[section Minimal]
`minimal_expr` below models _ExprTmpl_; since it has no operators, an
expression is built manually.
First, the template itself:
[minimal_template]
This can be used to make a `minimal_expr` plus expression:
[minimal_template_manual_construction]
You can evaluate, transform, or otherwise operate on `minimal_expr`
expressions using the functions in _yap_ that accept an _Expr_:
[minimal_template_evaluation]
[note Don't use _yap_ this way. Use the operator macros instead. This is an
example contrived only to show you the minimum requirements on a
_yap_-compatible template.]
[endsect]
[section Calc1]
This is the first of several calculator-building examples derived from Proto.
This first one just builds lazy expressions with placeholders, and evaluates
them. Here we can first see how much C++14-and-later language features help
the end user -- the Proto version is much, much longer.
[calc1]
[endsect]
[section Calc2]
The Proto Calc2 example turns the expressions from Calc1 into callable
objects. Using _yap_ you can do this in two ways.
You can just use lambdas to wrap the expressions:
[calc2a]
Or you can use _make_expr_fn_ to make a callable object from your expression:
[calc2b]
[endsect]
[section Calc3]
Here, we introduce a _XForm_ used to calculate expression arity, and
`static_assert()` that the number of parameters passed by the caller matches
the arity.
[note The `get_arity` _XForm_ doesn't produce an _Expr_, and it does not have
to. _XForms_ may produce _Exprs_ or arbitrary values. They may also have
arbitrary side effects, and may be stateful.]
[calc3]
[endsect]
[section Lazy Vector]
Finally, it starts to get interesting! This example shows how you can add
plus and other operations to sequences of data without creating temporaries
and allocating memory.
[note In this example, we see a terminal type that owns the storage of its
value, a `std::vector<double>`. See the Vector example later on to see a
terminal type that does not.]
[lazy_vector]
[endsect]
[section TArray]
Proto refers to this as the "mini-library for linear algebra" example. It
shows how quite complicated expressions involving sequences can be evaliated
elementwise, requiring no temporaries.
[note The original Proto example used a terminal that contained an array of
three `int`s; _yap_ cannot represent this, and so this example uses a
`std::array<T, 3>` instead. _yap_ decays `int[3]` to `int *`, since that is
what is done in a C++ expression. See _how_treated_ for details.]
[tarray]
[endsect]
[section Vec3]
An example using 3-space vectors, a bit like the tarray example.
[vec3]
[endsect]
[section Vector]
So far we've only seen examples with custom terminals that own the values in
the expressions we operate on. What happens when you've got types that you
want to operate on, non-intrusively? Here's how you might do it with
`std::vector<>`s:
[vector]
[note Though this example only provides overloads for the operations we want
to define over `std::vector<>`s, the result of each of those operations is an
_expr_, which uses *all* the operator overloads. If we wanted to restrict the
operations on the results too, we could have defined a custom expression
template with the desired operations, and used that instead of _expr_ in the
operator macros.]
[endsect]
[section Mixed]
This is a lot like the previous Vector example, except that it operates on
`std::vector<>`s and `std::list<>`s in the same expression. It also shows how
to override one of the operator-evaluation customization points.
[mixed]
[endsect]
[section Map Assign]
An implementation of `map_list_of()` from Boost.Assign using _yap_.
[map_assign]
[note `map_list_of_expr` defines a generic call operator that matches any
call, including one with the wrong number of arguments. This could be fixed
by adding a `static_assert()` to the `map_list_of_expr` template, or by
hand-writing the call operator with SFNIAE or concept constraints.]
[endsect]
[section Future Group]
An implementation of Howard Hinnant's design for /future groups/.
[future_group]
[endsect]
[endsect]