expr

Macro expr 

Source
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 expression

Advantages:

  • 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) cubed

IMPORTANT - 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 precedence

Right-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 = 512

Which 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:

  1. Method calls (highest): .pow(), .abs(), .sqrt(), .simplify()
  2. Power (right-associative): **
  3. Unary negation: -x
  4. Multiplication/division: *, /
  5. Addition/subtraction: +, -
  6. 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