context/
context.rs

1//! This example shows how to evaluate an expression with a variable and function in the context of
2//! the expression.
3
4extern crate mexprp;
5
6use mexprp::{Answer, Calculation, Context, Expression, MathError, Num, Term};
7
8fn main() {
9	// A context holds data that can be used in an expression
10	let mut context: Context<f64> = Context::new();
11	// Add a variable "x" to the context with the value 5.4
12	context.set_var("x", 5.4);
13	// Add a function "sum" to the context that returns the sum of it's arguments. A closure is passed
14	// in that takes twp arguments: args: &[Term], which is a slice if the arguments passed into the
15	// function, and ctx: &Context, which is a reference to the context which the expression is being
16	// evaluated with. The item passed in can be anything that implements the `Func` trait. There exists
17	// a blanket impl for Fn(&[Term], &Context) -> Calculation which allows you to pass in closures in
18	// that format.
19	context.set_func(
20		"sum",
21		|args: &[Term<f64>], ctx: &Context<f64>| -> Calculation<f64> {
22			if args.len() < 1 {
23				return Err(MathError::IncorrectArguments);
24			};
25
26			let mut sum = Answer::Single(0.0);
27			for arg in args {
28				let b = arg.eval_ctx(ctx)?;
29				sum = sum.op(&b, |a, b| Num::add(a, b, ctx))?;
30			}
31
32			Ok(sum)
33		},
34	);
35
36	let raw = "2 * sum(x, 7, 400)";
37	// The expression needs to be parsed with the context in order do decide if some names are functions
38	// or variables.
39	let expr = Expression::parse_ctx(raw, context).unwrap();
40	// The expression also needs to be evaluated with a context. This context can be different than the
41	// one it was parsed with, but if it is missing something that is necessary for evaluation the
42	// evaluation will fail.
43	println!("{} = {}", raw, expr.eval().unwrap())
44}