[][src]Module fasteval::evalns

Evaluation Namespaces used for Variable-lookups and custom Functions.

Several Evaluation Namespace types are defined, each with their own advantages:

Examples

EmptyNamespace

fn main() -> Result<(), fasteval::Error> {
    let mut ns = fasteval::EmptyNamespace;

    let val = fasteval::ez_eval("sin(pi()/2)", &mut ns)?;
    assert_eq!(val, 1.0);

    Ok(())
}

StringToF64Namespace

fn main() -> Result<(), fasteval::Error> {
    let mut ns = fasteval::StringToF64Namespace::new();
    ns.insert("x".to_string(), 2.0);

    let val = fasteval::ez_eval("x * (x + 1)", &mut ns)?;
    assert_eq!(val, 6.0);

    Ok(())
}

StrToF64Namespace

fn main() -> Result<(), fasteval::Error> {
    let mut ns = fasteval::StrToF64Namespace::new();
    ns.insert("x", 2.0);

    let val = fasteval::ez_eval("x * (x + 1)", &mut ns)?;
    assert_eq!(val, 6.0);

    Ok(())
}

Callback: FnMut(&str,Vec) -> Option

fn main() -> Result<(), fasteval::Error> {
    let mut num_lookups = 0;
    let mut cb = |name:&str, args:Vec<f64>| -> Option<f64> {
        num_lookups += 1;
        match name {
            "x" => Some(2.0),
            _ => None,
        }
    };

    let val = fasteval::ez_eval("x * (x + 1)", &mut cb)?;
    assert_eq!(val, 6.0);
    assert_eq!(num_lookups, 2);  // Notice that 'x' was looked-up twice.

    Ok(())
}

StringToCallbackNamespace

fn main() -> Result<(), fasteval::Error> {
    let mut ns = fasteval::StringToCallbackNamespace::new();
    ns.insert("x".to_string(), Box::new(|_args| 2.0));
    ns.insert("double".to_string(), Box::new(|args| {
        args.get(0).map(|arg0| arg0*2.0).unwrap_or(std::f64::NAN)
    }));

    let val = fasteval::ez_eval("double(x + 1) + 1", &mut ns)?;
    assert_eq!(val, 7.0);

    Ok(())
}

StrToCallbackNamespace

fn main() -> Result<(), fasteval::Error> {
    let mut ns = fasteval::StrToCallbackNamespace::new();
    ns.insert("x", Box::new(|_args| 2.0));
    ns.insert("double", Box::new(|args| {
        args.get(0).map(|arg0| arg0*2.0).unwrap_or(std::f64::NAN)
    }));

    let val = fasteval::ez_eval("double(x + 1) + 1", &mut ns)?;
    assert_eq!(val, 7.0);

    Ok(())
}

CachedCallbackNamespace

fn main() -> Result<(), fasteval::Error> {
    let mut num_lookups = 0;
    let val = {
        let cb = |name:&str, args:Vec<f64>| -> Option<f64> {
            num_lookups += 1;
            match name {
                "x" => {
                    // Pretend that it is very expensive to calculate this,
                    // and that's why we want to use the CachedCallbackNamespace cache.
                    for i in 0..1000000 { /* do work */ }  // Fake Work for this example.
                    Some(2.0)
                }
                _ => None,
            }
        };
        let mut ns = fasteval::CachedCallbackNamespace::new(cb);

        fasteval::ez_eval("x * (x + 1)", &mut ns)?
    };
    assert_eq!(val, 6.0);
    assert_eq!(num_lookups, 1);  // Notice that only 1 lookup occurred.
                                 // The second 'x' value was cached.

    Ok(())
}

LayeredStringToF64Namespace

fn main() -> Result<(), fasteval::Error> {
    let mut layer1 = fasteval::StringToF64Namespace::new();
    layer1.insert("x".to_string(), 2.0);
    layer1.insert("y".to_string(), 3.0);

    let mut layers : fasteval::LayeredStringToF64Namespace = vec![layer1];

    let val = fasteval::ez_eval("x * y", &mut layers)?;
    assert_eq!(val, 6.0);

    // Let's add another layer which shadows the previous one:
    let mut layer2 = fasteval::StringToF64Namespace::new();
    layer2.insert("x".to_string(), 3.0);
    layers.push(layer2);

    let val = fasteval::ez_eval("x * y", &mut layers)?;
    assert_eq!(val, 9.0);

    // Remove the top layer and we'll be back to what we had before:
    layers.pop();

    let val = fasteval::ez_eval("x * y", &mut layers)?;
    assert_eq!(val, 6.0);

    Ok(())
}

Custom Namespace Types

If the pre-defined Namespace types aren't perfect for your application, you can create your own namespace type -- just implemenet the EvalNamespace trait (and maybe the Cached and Layered traits too). Also, as fasteval becomes more mature and is used for more real-life things, I will continue to add more useful Namespace types.

Here are a few ideas of possibly-useful custom Namespace types:

  • Vec<Fn(&str,Vec)->Option> -- This would be a Layered namespace, with each layer having its own callback. Really powerful!

  • CachedCallbacksNamespace -- Same as above, but with a cache for each layer. Good for expensive look-ups.

Structs

CachedCallbackNamespace

CachedCallbackNamespace is useful when your variable/function lookups are expensive.

EmptyNamespace

Use EmptyNamespace when you know that you won't be looking up any variables.

Traits

Cached

Cache operations for EvalNamespaces.

EvalNamespace

All fasteval Namespaces must implement the EvalNamespace trait.

Type Definitions

LayeredStringToF64Namespace

Type alias for Vec<BTreeMap<String,f64>>

StrToCallbackNamespace

Type alias for BTreeMap<&'static str, Box<dyn FnMut(Vec<f64>)->f64>>

StrToF64Namespace

Type alias for BTreeMap<&'static str,f64>

StringToCallbackNamespace

Type alias for BTreeMap<String, Box<dyn FnMut(Vec<f64>)->f64>>

StringToF64Namespace

Type alias for BTreeMap<String,f64>