pub enum Val<I = i32, F = f64>{
Array(ArrayType<F>),
Int(I),
Float(F),
Bool(bool),
Error(ExError),
None,
}
Expand description
feature = "value"
-
The value type Val
can contain an integer, float, bool, a vector of floats, none, or error.
To use the value type, there are the is a parse function parse_val
.
In the following example, the ternary Python-style a if condition else b
is used.
This is equivalent to if condition {a} else {b}
in Rust or condition ? a : b
in C.
use exmex::{Express, Val};
let expr = exmex::parse_val::<i32, f64>("1.0 if x > y else 73")?;
assert_eq!(expr.eval(&[Val::Float(3.4), Val::Int(3)])?.to_float()?, 1.0);
assert_eq!(expr.eval(&[Val::Int(34), Val::Float(132.0)])?.to_int()?, 73);
Note that the ternary operator is actually implemented as two binary operators called if
and else
.
To this end, we return Val::None
from the if
-operator if and only if the condition is false. On the flipside,
this has strange side effects such as 5 else 3
being a valid expression evaluating to 5.
use exmex::Express;
let expr = exmex::parse_val::<i32, f64>("5 else 3")?;
assert_eq!(expr.eval(&[])?.to_int()?, 5);
We use the variant Error
to report errors, since the trait Try
is not yet stable.
use exmex::Express;
let expr = exmex::parse_val::<i32, f64>("fact(3.5)")?;
let res = expr.eval(&[])?;
assert!(format!("{:?}", res) == "Error(ExError { msg: \"did not expect Float(3.5)\" })");
When converting the value to the expected primitive type with to_int
, to_float
, or to_bool
, the case Val::Error(ExError)
is
converted to ExResult::Err(ExError)
.
assert!(res.to_int().is_err());
Vectors can have arbitrary length and are represented as Val::Array(SmallVec<[F; 4]>)
. That
is, a vector always consists of floats. Vectors of bools or ints do not exist. Further,
4 elements are stored on the stack, and if more are needed, they are stored on the heap.
An example with vectors is shown in the following.
use exmex::Val;
use smallvec::smallvec;
// dot product of two vectors, one as parameter the other as literal
let expr = exmex::parse_val::<i32, f64>("dot(v, [1, 0, 0])")?;
let v = Val::Array(smallvec![3.0, 4.0, 2.0]);
let res = expr.eval(&[v])?;
assert!(res.to_float()? == 3.0);
// The following example shows how to get the second component of a vector
let expr = exmex::parse_val::<i32, f64>("(v + [1, 0, 0]).2")?;
let v = Val::Array(smallvec![3.0, 4.0, 2.0]);
let res = expr.eval(&[v])?;
assert!(res.to_float()? == 2.0);
Variants§
Array(ArrayType<F>)
Int(I)
Float(F)
Bool(bool)
Error(ExError)
Since the trait Try
is experimental, we keep track of an error in an additional variant.
None
Sometimes, Val
does not contain a value
Implementations§
Trait Implementations§
source§impl<I, F> MakeOperators<Val<I, F>> for ValOpsFactory<I, F>
impl<I, F> MakeOperators<Val<I, F>> for ValOpsFactory<I, F>
source§impl<I, F> PartialEq for Val<I, F>
impl<I, F> PartialEq for Val<I, F>
source§impl<I, F> PartialOrd for Val<I, F>
impl<I, F> PartialOrd for Val<I, F>
1.0.0 · source§fn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
self
and other
) and is used by the <=
operator. Read more