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:

  1. A representation of the expression that you want to produce.
  2. A comma separated list of variable names used in the expression body.
  3. 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.