advanced_vars/advanced-vars.rs
1// usage: cargo run --release --example advanced-vars
2
3fn main() -> Result<(), fasteval3::Error> {
4 let mut cb = |name: &str, args: Vec<f64>| -> Option<f64> {
5 let mydata: [f64; 3] = [11.1, 22.2, 33.3];
6 match name {
7 // Custom constants/variables:
8 "x" => Some(3.0),
9 "y" => Some(4.0),
10
11 // Custom function:
12 "sum" => Some(args.into_iter().fold(0.0, |s, f| s + f)),
13
14 // Custom array-like objects:
15 // The `args.get...` code is the same as:
16 // mydata[args[0] as usize]
17 // ...but it won't panic if either index is out-of-bounds.
18 "data" => {
19 args.first().and_then(|f| mydata.get(*f as usize).copied())
20 },
21
22 // A wildcard to handle all undefined names:
23 _ => None,
24 }
25 };
26
27 let val = fasteval3::ez_eval("sum(x^2, y^2)^0.5 + data[0]", &mut cb)?;
28 // | | |
29 // | | square-brackets act like parenthesis
30 // | variables are like custom functions with zero args
31 // custom function
32
33 assert!((val - 16.1).abs() < f64::EPSILON);
34
35 // Let's explore some of the hidden complexities of variables:
36 //
37 // * There's really no difference between a variable and a custom function.
38 // Therefore, variables can receive arguments too,
39 // which will probably be ignored.
40 // Therefore, these two expressions evaluate to the same thing:
41 // eval("x + y") == eval("x(1,2,3) + y(x, y, sum(x,y))")
42 // ^^^^^ ^^^^^^^^^^^^^^
43 // All this stuff is ignored.
44 //
45 // * Built-in functions take precedence WHEN CALLED AS FUNCTIONS.
46 // This design was chosen so that builtin functions do not pollute
47 // the variable namespace, which is important for some applications.
48 // Here are some examples:
49 // pi -- Uses the custom 'pi' variable, NOT the builtin 'pi' function.
50 // pi() -- Uses the builtin 'pi' function even if a custom variable is defined.
51 // pi(1,2,3) -- Uses the builtin 'pi' function, and produces a WrongArgs error
52 // during parse because the builtin does not expect any arguments.
53 // x -- Uses the custom 'x' variable.
54 // x() -- Uses the custom 'x' variable because there is no 'x' builtin.
55 // x(1,2,3) -- Uses the custom 'x' variable. The args are ignored.
56 // sum -- Uses the custom 'sum' function with no arguments.
57 // sum() -- Uses the custom 'sum' function with no arguments.
58 // sum(1,2) -- Uses the custom 'sum' function with two arguments.
59
60 Ok(())
61}