expr!() { /* proc-macro */ }
Expand description
Generate a ExprFix
expression.
expr!(<expr>; var1 [= <expr>], …[; iden1 [= <expr>], …])
The macro body consists of 3 semicolon separated parts:
- A representation of the expression that you want to produce.
- A comma separated list of Var names used in the expression body.
- An optional comma separated list of names for Par or f64 values.
The names used to represent variables must be simple identifiers. The
identifiers must either be present in the environment as legitimate Var
values that can be copied into the expression, or the special syntax name = expression
can be used in the list of variable or parameter names (parts
2 and 3) to conveniently declare them in a local scope.
Anything that appears in the expression is captured (moved) from the environment (or local scope), similarly to a closure. There are in fact multiple closures being created behind the scenes, so anything that is captured needs to implement copy.
§Examples
#![feature(proc_macro_hygiene)] // need to turn on nightly feature
use descent::expr::{Var, Par};
use descent_macro::expr;
let x = Var(0);
let y = Var(1);
let p = Par(0);
let c = 1.0;
let e = expr!(p * x + y * y + c; x, y);
Syntax for scoped declaration of variables / parameters:
#![feature(proc_macro_hygiene)] // need to turn on nightly feature
use descent::expr::{Var, Par};
use descent_macro::expr;
let vars = [Var(0), Var(1)];
let pars = [Par(0)];
let constant = vec![1.0, 2.0];
let e = expr!(a * x + y * y + c; x = vars[0], y = vars[1]; a = pars[0], c = constant[0]);
This is a shorthand for the following, which is required to make sure the
values can be copied into the internal closures (e.g., directly using
constant[0]
would attempt result in attempting to move the Vec constant
multiple times):
let e = {
let x = vars[0];
let y = vars[1];
let a = pars[0];
let c = constant[0];
expr!(a * x + y * y + c; x, y;)
}