Build Status meval at docs.rs

meval

This [Rust] crate provides a simple math expression parsing and evaluation. Its main goal is to be convenient to use, while allowing for some flexibility. Currently works only with f64 types. A typical use case is the configuration of numerical computations in Rust, think initial data and boundary conditions, via config files or command line arguments.

Documentation

Installation

Simply add the corresponding entry to your Cargo.toml dependency list:

toml [dependencies] meval = "0.1"

and add this to your crate root:

rust extern crate meval;

Simple examples

```rust extern crate meval;

fn main() { let r = meval::eval_str("1 + 2").unwrap();

println!("1 + 2 = {}", r);

} ```

Need to define a Rust function from an expression? No problem, use Expr for this and more:

```rust extern crate meval;

fn main() { let expr: meval::Expr = "sin(pi * x)".parse().unwrap(); let func = expr.bind("x").unwrap();

let vs: Vec<_> = (0..100+1).map(|i| func(i as f64 / 100.)).collect();

println!("sin(pi * x), 0 <= x <= 1: {:?}", vs);

} ```

Expr::bind returns a boxed closure that is slightly less convenient than an unboxed closure since Box<Fn(f64) -> f64> does not implement FnOnce, Fn or FnMut. So to use it directly as a function argument where a closure is expected, it has to be manually dereferenced:

rust let func = "x".parse::<meval::Expr>().unwrap().bind("x").unwrap(); let r = Some(2.).map(&*func);

Custom constants and functions? Define a Context!

```rust use meval::{Expr, Context};

let y = 1.; let expr: Expr = "phi(-2 * zeta + x)".parse().unwrap();

// create a context with function definitions and variables let mut ctx = Context::new(); // built-ins ctx.func("phi", |x| x + y) .var("zeta", -1.); // bind function with a custom context let func = expr.bindwithcontext(ctx, "x").unwrap(); assert_eq!(func(2.), -2. * -1. + 2. + 1.); ```

For functions of 2, 3, and N variables use Context::func2, Context::func3 and Context::funcn, respectively. See Context for more options.

If you need a custom function depending on mutable parameters, you will need to use a Cell:

```rust use std::cell::Cell; use meval::{Expr, Context}; let y = Cell::new(0.); let expr: Expr = "phi(x)".parse().unwrap();

let mut ctx = Context::empty(); // no built-ins ctx.func("phi", |x| x + y.get());

let func = expr.bindwithcontext(ctx, "x").unwrap(); asserteq!(func(2.), 2.); y.set(3.); asserteq!(func(2.), 5.); ```

Supported expressions

meval supports basic mathematical operations on floating point numbers:

It supports custom variables and functions like x, weight, C_0, f(1), etc. A variable or function name must start with [a-zA-Z_] and can contain only [a-zA-Z0-9_]. Custom functions with a variable number of arguments are also supported.

Build-ins (given by the context Context::new() and when no context provided) currently supported:

Deserialization

Expr supports deserialization using the [serde] library to make flexible configuration easy to set up, if the feature serde is enabled (disabled by default).

```rust

[macro_use]

extern crate serde_derive; extern crate toml; extern crate meval; use meval::{Expr, Context};

[derive(Deserialize)]

struct Ode { #[serde(deserializewith = "meval::de::asf64")] x0: f64, #[serde(deserializewith = "meval::de::asf64")] t0: f64, f: Expr, }

fn main() { let config = r#" x0 = "cos(1.)" t0 = 2 f = "sin(x)" "#; let ode: Ode = toml::from_str(config).unwrap();

assert_eq!(ode.x0, 1f64.cos());
assert_eq!(ode.t0, 2f64);
assert_eq!(ode.f.bind("x").unwrap()(2.), 2f64.sin());

}

```

Related projects

This is a toy project of mine for learning Rust, and to be hopefully useful when writing command line scripts. There is no plan to make this anything more than math expression -> number "converter". For more advanced scripting, see:

License

This project is dual-licensed under the Unlicense and MIT licenses.

You may use this code under the terms of either license.