Macro descent_macro::expr
source · expr!() { /* proc-macro */ }
Expand description
Generate a ExprFix
expression.
expr!(<expr>; var1 [= <expr>], …[; par1 [= <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 variable names used in the expression body.
- An optional comma separated list of parameter names used in the expression body.
The variable and parameter names must be simple identifiers. The
identifiers must either be present in the environment as legitimate Var
or Par
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 automatically declare them in a local scope.
Constants and other expressions used in the expression are captured (moved) from the environment, 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; p);
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 c = constant[0];
let e = expr!(a * x + y * y + c; x = vars[0], y = vars[1]; a = pars[0]);
This convenience currently hasn’t been extended to constant terms. So in
the above we need to explicitly declare c
in the environment so that the
closures don’t try to move the whole constant
vector multiple times.