Context

Struct Context 

Source
pub struct Context<N: Num> {
    pub vars: HashMap<String, Term<N>>,
    pub funcs: HashMap<String, Rc<dyn Func<N>>>,
    pub cfg: Config,
}
Expand description

A context holds values for variables and functions to be used in expressions. It is useful for both parsing and evaluation expressions. During parsing, all names will be treated as variables unless present in the Context the expression is being parsed with as functions at the time. The default context (created with new()) contains basic functions and constants such as sin, pi, etc, as well as the default configuration.

Contexts are used differently with Terms and Expressions. With Terms, more decisions are left up to the user. Terms can be parsed with a reference to a context and evaluated with a reference to a context. They never store any contextual information themselves. Expressions can be parsed with an instance of a Context and will then store that Context within them. They can still be evaluated with a reference to any other Context.

To define a custom variable, use set_var. It takes anything that implements Into<Term>, so you can pass in just an f64 if you want.

let mut context: Context<f64> = Context::new();
context.set_var("x", 4.0);
let expr = Expression::parse_ctx("4x", context).unwrap();
let res = expr.eval(); // Ok(Answer::Single(16.0))

A custom function is anything that implements the func::Func trait. There’s a blanket impl of this trait allowing you to pass in any closure with the signature Fn(&[Term<Num>], &Context<Num>) -> Calculation<Num>. You can also pass in a struct that implements Func manually if you want more flexibility. The Func trait is just one method with the same signature previously mentioned. Defining a custom function will most often look like this.

let mut context: Context<f64> = Context::new();
context.set_func("sum", |args: &[Term<f64>], ctx: &Context<f64>| -> Calculation<f64> {
    if args.is_empty() { return Err(MathError::IncorrectArguments) }

    let mut sum = 0.0;
    for arg in args {
        let a = arg.eval_ctx(ctx)?;
        match a {
            Answer::Single(n) => sum += n,
            Answer::Multiple(ns) => {
                for n in ns {
                    sum += n;
                }
            }
        }
    }
    Ok(Answer::Single(sum))
});
let expr = Expression::parse_ctx("sum(5, 6, 7, 8)", context).unwrap();
let res = expr.eval(); // Ok(Answer::Single(26.0))

The first argument of a custom function definition is a slice of Terms, which are the arguments passed to the functions. The second argument is a reference to the Context the equation is being evaluated with. It’s important to remember to evaluate any arguments you receive with the reference to the Context you received with Term::eval_ctx(). If the function is given arguments in an incorrect way, return a MathError::IncorrectArguments. If any errors occur during evaluation, you can try to find a MathError variant that fits or return MathError::Other.

§Builtin

§Constants

  • pi
  • e
  • i

§Functions

  • sin
  • cos
  • tan
  • asin
  • acos
  • atan
  • atant (atan2)
  • floor
  • ceil
  • round
  • sqrt
  • max
  • min

Fields§

§vars: HashMap<String, Term<N>>

HashMap of variables

§funcs: HashMap<String, Rc<dyn Func<N>>>

HashMap of functions

§cfg: Config

The configuration used when evaluating expressions

Implementations§

Source§

impl<N: Num + 'static> Context<N>

Source

pub fn new() -> Self

Returns a default Context

Examples found in repository?
examples/context.rs (line 10)
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}
Source

pub fn set_var<T: Into<Term<N>>>(&mut self, name: &str, val: T)

Add a variable definition to the context, replacing any existing one with the same name

Examples found in repository?
examples/context.rs (line 12)
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}
Source

pub fn set_func<F: Func<N> + 'static>(&mut self, name: &str, func: F)

Add a function definition to the context, replacing any existing one with the same name

Examples found in repository?
examples/context.rs (lines 19-34)
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}
Source

pub fn empty() -> Self

Creates an empty Context with the default config

Trait Implementations§

Source§

impl<N: Clone + Num> Clone for Context<N>

Source§

fn clone(&self) -> Context<N>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<N: Num> Debug for Context<N>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<N: Num + 'static> Default for Context<N>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<N> Freeze for Context<N>

§

impl<N> !RefUnwindSafe for Context<N>

§

impl<N> !Send for Context<N>

§

impl<N> !Sync for Context<N>

§

impl<N> Unpin for Context<N>
where N: Unpin,

§

impl<N> !UnwindSafe for Context<N>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Az for T

Source§

fn az<Dst>(self) -> Dst
where T: Cast<Dst>,

Casts the value.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CheckedAs for T

Source§

fn checked_as<Dst>(self) -> Option<Dst>
where T: CheckedCast<Dst>,

Casts the value.
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> OverflowingAs for T

Source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where T: OverflowingCast<Dst>,

Casts the value.
Source§

impl<T> SaturatingAs for T

Source§

fn saturating_as<Dst>(self) -> Dst
where T: SaturatingCast<Dst>,

Casts the value.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> UnwrappedAs for T

Source§

fn unwrapped_as<Dst>(self) -> Dst
where T: UnwrappedCast<Dst>,

Casts the value.
Source§

impl<T> WrappingAs for T

Source§

fn wrapping_as<Dst>(self) -> Dst
where T: WrappingCast<Dst>,

Casts the value.