Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Evaluate Expressions Only

Tip: Dynamic

Use Dynamic if you’re uncertain of the return type.

Very often, a use case does not require a full-blown scripting language, but only needs to evaluate expressions.

In these cases, use the Engine::compile_expression and Engine::eval_expression methods or their _with_scope variants.

let result: i64 = engine.eval_expression("2 + (10 + 10) * 2")?;

let result: Dynamic = engine.eval_expression("get_value(42)")?;

// Usually this is done together with a custom scope with variables...

let mut scope = Scope::new();

scope.push("x", 42_i64);
scope.push_constant("SCALE", 10_i64);

let result: i64 = engine.eval_expression_with_scope(&mut scope,
                        "(x + 1) * SCALE"
                  )?;

No statements allowed

When evaluating expressions, no full-blown statement (e.g. while, for, fn) – not even variable assignment – is supported and will be considered syntax errors.

This is true also for statement expressions and closures.

// The following are all syntax errors because the script
// is not a strict expression.

engine.eval_expression::<()>("x = 42")?;

let ast = engine.compile_expression("let x = 42")?;

let result = engine.eval_expression_with_scope::<i64>(&mut scope,
                    "{ let y = calc(x); x + y }"
             )?;

let fp: FnPtr = engine.eval_expression("|x| x + 1")?;

Tip: if-expressions and switch-expressions

if expressions are allowed if both statement blocks contain only a single expression each.

switch expressions are allowed if all match actions are expressions and not statements.

loop expressions are not allowed.

// The following are allowed.

let result = engine.eval_expression_with_scope::<i64>(&mut scope,
                    "if x { 42 } else { 123 }"
             )?;

let result = engine.eval_expression_with_scope::<i64>(&mut scope, "
                    switch x {
                        0 => x * 42,
                        1..=9 => foo(123) + bar(1),
                        10 => 0,
                    }
             ")?;

Evaluate a Binary Operation

Sometimes it is desirable to evaluate a binary operation directly, without the need to create a script. This is especially useful when comparing two Dynamic values.

Use Engine::eval_binary_op to evaluate a binary operation directly.

let x = 123;         // Integer value
let y = 123.0;       // Floating-point value

// Run the '==' operator to compare the two values.
// Rhai returns 'true' because they are the same, though of different types.
let result = engine.eval_binary_op("==", x, y)?;
//                                 ^^^^
//                                 Operator to evaluate

// Rhai has built-in array comparison as well as for all supported types.
let x = [1, 2, true, "hello"];
let y = [1, 2, true, "hello"];

let result = engine.eval_binary_op("==", x, y)?;

Tip: Rhai built-in comparisons

Rhai automatically handles comparisons between different Dynamic value types that are expected by causal script users, e.g. floating-point vs integer, "A" (a string) vs 'A' (a character) etc.

See here for more details.

Evaluate an Arbitrary Function Call

Sometimes it is desirable to evaluate a function call directly, without the need to create a script.

Use Engine::eval_fn_call to evaluate an arbitrary function call. It does not matter whether the function is a Rhai-scripted function, a registered Rust function, a built-in function, or a function in one of the loaded modules.

let result = engine.eval_fn_call("foo", None, (123, true))?;
//                                            ^^^^^^^^^^^
//                                            Arguments
//                                      ^^^^
//                                      'this' pointer, if any