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}