Variable Resolver
By default, Rhai looks up access to variables from the enclosing block scope, working its way
outwards until it reaches the top (global) level, then it searches the Scope
that is passed into
the Engine::eval
call.
There is a built-in facility for advanced users to hook into the variable resolution service and to override its default behavior.
To do so, provide a closure to the Engine
via Engine::on_var
.
let mut engine = Engine::new();
// Register a variable resolver.
engine.on_var(|name, index, context| {
match name {
"MYSTIC_NUMBER" => Ok(Some(42_i64.into())),
// Override a variable - make it not found even if it exists!
"DO_NOT_USE" => Err(EvalAltResult::ErrorVariableNotFound(name.to_string(), Position::NONE).into()),
// Silently maps 'chameleon' into 'innocent'.
"chameleon" => context.scope().get_value("innocent").map(Some).ok_or_else(||
EvalAltResult::ErrorVariableNotFound(name.to_string(), Position::NONE).into()
),
// Return Ok(None) to continue with the normal variable resolution process.
_ => Ok(None)
}
});
-
Avoid having to maintain a custom
Scope
with all variables regardless of need (because a script may not use them all). -
Short-circuit variable access, essentially overriding standard behavior.
-
Lazy-load variables when they are accessed, not up-front. This benefits when the number of variables is very large, when they are timing-dependent, or when they are expensive to load.
-
Rename system variables on a script-by-script basis without having to construct different
Scope
’s.
Function Signature
The function signature passed to Engine::on_var
takes the following form.
Fn(name: &str, index: usize, context: EvalContext) -> Result<Option<Dynamic>, Box<EvalAltResult>>
where:
Parameter | Type | Description |
---|---|---|
name | &str | variable name |
index | usize | an offset from the bottom of the current Scope that the variable is supposed to reside.Offsets start from 1, with 1 meaning the last variable in the current Scope . Essentially the correct variable is at position scope.len() - index .If index is zero, then there is no pre-calculated offset position and a search through the current Scope must be performed. |
context | EvalContext | mutable reference to the current evaluation context |
and EvalContext
is a type that encapsulates the current evaluation context.
Return value
The return value is Result<Option<Dynamic>, Box<EvalAltResult>>
where:
Value | Description |
---|---|
Ok(None) | normal variable resolution process should continue, i.e. continue searching through the Scope |
Ok(Some(value)) | value (a Dynamic ) of the variable, treated as a constant |
Err(Box<EvalAltResult>) | error that is reflected back to the Engine , normally EvalAltResult::ErrorVariableNotFound to indicate that the variable does not exist, but it can be any EvalAltResult . |