[−][src]Module fasteval::evalns
Evaluation Namespaces used for Variable-lookups and custom Functions.
Several Evaluation Namespace types are defined, each with their own advantages:
EmptyNamespace
-- Useful when you know that your expressions don't need to look up any variables.- BTreeMap -- A simple way to define variables and functions with a map. Type aliases: StringToF64Namespace, StrToF64Namespace, StringToCallbackNamespace, StrToCallbackNamespace
FnMut(&str,Vec<f64>) -> Option<f64>
-- Define variables and custom functions using a callback function.CachedCallbackNamespace
-- Like the above callback-based Namespace, but results are cached so the callback is not queried more than once for a given variable.- Vec<BTreeMap<String,f64>> -- Define variables with layered maps. Each layer is a separate 'scope'. Higher layers take precedence over lower layers. Very useful for creating scoped higher-level-languages. Type alias: LayeredStringToF64Namespace
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 |
|
EmptyNamespace | Use |
Traits
Cached | Cache operations for |
EvalNamespace | All |
Type Definitions
LayeredStringToF64Namespace | Type alias for |
StrToCallbackNamespace | Type alias for |
StrToF64Namespace | Type alias for |
StringToCallbackNamespace | Type alias for |
StringToF64Namespace | Type alias for |