expr!() { /* proc-macro */ }Expand description
Procedural macro for creating mathematical expressions with full syntax support
§Supported Operators
- Basic arithmetic:
+,-,*,/ - Unary negation:
-x - Power operations: Both
**and.pow()syntax - Comparison operators:
==,<,>,<=,>=
§Supported Literals
- Integers:
42,-5,0 - Floats:
3.14,-2.5,0.0 - Identifiers/symbols:
x,theta,alpha_1 - Mathematical constants:
pi,e,i
§Supported Constructs
- Function calls:
sin(x),log(x, y),f(a, b, c) - Parenthesized expressions:
(2*x + 3),((x+y)) - Method calls:
x.pow(2),x.abs(),x.sqrt(),x.simplify()
§Power Operator Syntax
The macro supports two syntaxes for exponentiation:
§Method Syntax: .pow()
The .pow() method works everywhere without restrictions:
ⓘ
expr!(x.pow(2)) // x squared
expr!(x.pow(y)) // x to the y
expr!((x + 1).pow(3)) // (x+1) cubed
expr!(2 * x.pow(3) + 5) // Complex expressionAdvantages:
- Mirrors Rust’s standard library API
- Works seamlessly in any context
- Clear, unambiguous precedence
- No parentheses required
§Infix Syntax: **
The ** operator provides mathematical notation:
ⓘ
expr!(x ** 2) // x squared
expr!(x ** y) // x to the y
expr!((x + 1) ** 3) // (x+1) cubedIMPORTANT - When to use parentheses with **:
Due to token-level preprocessing, complex expressions with ** should use
parentheses for clarity when mixing with other operators:
ⓘ
// ✅ RECOMMENDED (clear precedence):
expr!(2 * (x ** 3) + 5) // Parentheses make precedence explicit
expr!((x ** 2) + (y ** 2)) // Clear grouping
// ⚠️ WORKS BUT LESS CLEAR:
expr!(x ** 2 + y ** 2) // Relies on implicit precedenceRight-associativity:
Power operations are right-associative (like standard mathematical notation):
ⓘ
expr!(x ** 2 ** 3) // Parsed as: x ** (2 ** 3) = x ** 8
expr!(2 ** 3 ** 2) // Parsed as: 2 ** (3 ** 2) = 2 ** 9 = 512Which syntax to use?
- Use
.pow()for guaranteed clarity in complex expressions - Use
**when writing simple mathematical formulas that match notation - When in doubt, add parentheses:
expr!(2 * (x ** 3) + 5)
§Examples
ⓘ
use mathhook_macros::expr;
use mathhook_core::{Expression, symbol};
let x = symbol!(x);
let y = symbol!(y);
// Basic operations
let sum = expr!(x + 2);
let product = expr!(2 * x);
// Power operations (both syntaxes work)
let power1 = expr!(x ** 2);
let power2 = expr!(x.pow(2));
// Complex expressions (use parentheses with ** for clarity)
let quadratic = expr!((x ** 2) + 2*x + 1);
let nested = expr!((x + 1) * (x - 1));
let functions = expr!(sin(x ** 2));
// Comparison operators
let equation = expr!(x ** 2 == 4);
let inequality = expr!(x + 1 > y);
// Method calls
let abs_val = expr!(x.abs());
let sqrt_expr = expr!(x.sqrt());
let simplified = expr!((x + x).simplify());§Precedence Rules
Operator precedence from highest to lowest:
- Method calls (highest):
.pow(),.abs(),.sqrt(),.simplify() - Power (right-associative):
** - Unary negation:
-x - Multiplication/division:
*,/ - Addition/subtraction:
+,- - Comparison operators (lowest):
==,<,>,<=,>=
Use parentheses to override precedence:
ⓘ
expr!(2 * x + 3) // Parsed as: (2*x) + 3
expr!((2 + 3) * x) // Parentheses override: 5*x
expr!(2 * (x ** 3)) // Recommended for clarity with **
expr!((x + 1) ** 2) // Power of sum