7b7935b0d0
Fixes #46.
99 lines
4.0 KiB
Plaintext
99 lines
4.0 KiB
Plaintext
[section Introduction]
|
|
|
|
"I like to start documentation with a quote. A nice, pithy one."
|
|
|
|
['[*_emdash_ Eric Niebler (paraphrased)]]
|
|
|
|
[heading Motivation]
|
|
|
|
_Ets_ are rad. They are used in lots of libraries; here are just three of the
|
|
most impressive:
|
|
|
|
* _spirit_ allows you to write an EBNF-style grammar that gets transformed
|
|
into a PEG parser.
|
|
|
|
* _eigen_ allows you to do linear algebra using a very natural and
|
|
mathematical expression syntax that _eigen_ uses to heavily optimize your
|
|
expressions.
|
|
|
|
* _nt2_ takes slightly modified MatLab code and allows it to be parsed and run
|
|
as highly optimized C++ code.
|
|
|
|
However, this can come at a high cost. _Ets_ are costly to implement and
|
|
maintain. Each of _eigen_ and Boost.Ublas has a large volume of complex _et_
|
|
code that cannot be reused elsewhere.
|
|
|
|
With the language facilities available in the C++14 and C++17 standards, an
|
|
_et_ library is now straightforward to write and use, and has very reasonable
|
|
compile times.
|
|
|
|
As a quick example, let's say we are doing a bit of matrix math, and we write
|
|
this statement:
|
|
|
|
D = A * B + C;
|
|
|
|
in which all the variables are matrices. It turns out that making a temporary
|
|
for `A * B` and then another temporary for the resulting product plus `C` is
|
|
very inefficient. Most matrix math libraries will have a single function that
|
|
does it in one go:
|
|
|
|
mul_add_assign(D, A, B, C);
|
|
|
|
If you use a matrix library that offers both kinds of syntax, you have to
|
|
notice when some bit of operator-using code should be replaced with some more
|
|
efficient function; this is tedious and error-prone. If the library does not
|
|
provide the operator syntax at all, only providing the more-efficient function
|
|
calls, code using the library is a lot less writable and readable.
|
|
|
|
Using _yap_, you can write some library code that enables expressions like `D
|
|
= A * B + C` to be automatically transformed into expressions like
|
|
`mul_add_assign(D, A, B, C)`.
|
|
|
|
Consider another example. Many of us have used Unix command line tools to
|
|
remove duplicate lines in a file:
|
|
|
|
sort file_with_duplicates | uniq > file_without_duplicates
|
|
|
|
We can do something very similar with the standard algorithms, of course:
|
|
|
|
[typical_sort_unique_usage]
|
|
|
|
However, it would be much better if our code did exactly that, but with a more
|
|
concise syntax:
|
|
|
|
[pipable_sort_unique_usage]
|
|
|
|
This looks much more similar to the Unix command line above. (Let's pretend
|
|
that _range_v3_ doesn't already do almost exactly this.)
|
|
|
|
_yap_ can be used to do both of these things, in a pretty small amount of
|
|
code. In fact, you can jump right into the _pipable_algorithms_ example if
|
|
you want to see how the second one can be implemented.
|
|
|
|
[heading Features]
|
|
|
|
* Simple _ExprTmpl_ and _Expr_ concepts easily modeled by user code. Member
|
|
and non-member functions on _ExprTmpls_ and _Exprs_ can be added with
|
|
compact macros, and a reference template that models _ExprTmpl_ exists for
|
|
prototyping or experimentation.
|
|
|
|
* Evaluation of _yap_ expressions matches the semantics of builtin C++
|
|
expressions as closely as possible. This leads to clearer understanding of
|
|
the semantics of expression evaluation, because the definitions are local to
|
|
the types involved.
|
|
|
|
* Expressions may be transformed explicitly in a user-defined way. This is
|
|
accomplished with overloaded call operators in a transform class, which are
|
|
matched against subexpressions in the overall expression. While these
|
|
member functions may transform a subexpression into anything, a common
|
|
pattern is to transform only some subexpressions into either new
|
|
subexpressions or appropriate values and to leave other subexpressions
|
|
unchanged. This `evaluate(transform(expr))` idiom is expected to be one of
|
|
the most common ways of using Yap to manipulate and evaluate expressions.
|
|
|
|
* Functions that operate on or create expressions. Functions are provided
|
|
(and used within _yap_) that manipulate expressions or their subexpressions.
|
|
These simplify the process of writing user-defined transforms, for example.
|
|
|
|
[endsect]
|