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}