Variables

Valid Names


The [`unicode-xid-ident`] feature expands the allowed characters for variable names to the set defined by
[Unicode Standard Annex #31](http://www.unicode.org/reports/tr31/).

Variables in Rhai follow normal C naming rules – must contain only ASCII letters, digits and underscores _.

Character setDescription
AZUpper-case ASCII letters
azLower-case ASCII letters
09Digit characters
_Underscore character

However, unlike Rust, a variable name must also contain at least one ASCII letter, and an ASCII letter must come before any digits. In other words, the first character that is not an underscore _ must be an ASCII letter and not a digit.


To reduce confusion (and subtle bugs) because, for instance, `_1` can easily be misread (or mistyped)
as `-1`.

Rhai is dynamic without type checking, so there is no compiler to catch these typos.

Therefore, some names acceptable to Rust, like _, _42foo, _1 etc., are not valid in Rhai.

For example: c3po and _r2d2_ are valid variable names, but 3abc and ____49steps are not.

Variable names are case sensitive.

Variable names also cannot be the same as a keyword (active or reserved).


Rhai uses [`SmartString`] which avoids allocations unless a string is over its internal limit
(23 ASCII characters on 64-bit, but only 11 ASCII characters on 32-bit).

On 64-bit systems, _most_ variable names are shorter than 23 letters, so this is unlikely to become
an issue.

However, on 32-bit systems, take care to limit, where possible, variable names to within 11 letters.
This is particularly true for local variables inside a hot loop, where they are created and
destroyed in rapid succession.

~~~js
// The following is SLOW on 32-bit
for my_super_loop_variable in array {
    print(`Super! ${my_super_loop_variable}`);
}

// Suggested revision:
for loop_var in array {
    print(`Super! ${loop_var}`);
}
~~~

Declare a Variable

Variables are declared using the let keyword.


Variables do not have to be given an initial value.
If none is provided, it defaults to [`()`].

A variable defined within a [statements block](statements.md) is _local_ to that block.

Use `is_def_var` to detect if a variable is defined.
let x;              // ok - value is '()'
let x = 3;          // ok
let _x = 42;        // ok
let x_ = 42;        // also ok
let _x_ = 42;       // still ok

let _ = 123;        // <- syntax error: illegal variable name
let _9 = 9;         // <- syntax error: illegal variable name

let x = 42;         // variable is 'x', lower case
let X = 123;        // variable is 'X', upper case

print(x);           // prints 42
print(X);           // prints 123

{
    let x = 999;    // local variable 'x' shadows the 'x' in parent block

    print(x);       // prints 999
}

print(x);           // prints 42 - the parent block's 'x' is not changed

let x = 0;          // new variable 'x' shadows the old 'x'

print(x);           // prints 0

is_def_var("x") == true;

is_def_var("_x") == true;

is_def_var("y") == false;

Use Before Definition

By default, variables do not need to be defined before they are used.

If a variable accessed by a script is not defined previously within the same script, it is assumed to be provided via an external custom Scope passed to the Engine via the Engine::XXX_with_scope API.

let engine = Engine::new();

engine.run("print(answer)")?;       // <- error: variable 'answer' not found

// Create custom scope
let mut scope = Scope::new();

// Add variable to custom scope
scope.push("answer", 42_i64);

// Run with custom scope
engine.run_with_scope(&mut scope,
    "print(answer)"                 // <- prints 42
)?;

If no [`Scope`] is used to evaluate the script (e.g. when using `Engine::run` instead of
`Engine::run_with_scope`), an undefined variable causes a runtime error when accessed.

Strict Variables Mode

With Engine::set_strict_variables, it is possible to turn on Strict Variables mode.

When strict variables mode is active, accessing a variable not previously defined within the same script directly causes a parse error when compiling the script.

let x = 42;

print(x);           // prints 42

print(foo);         // <- parse error under strict variables mode:
                    //    variable 'foo' is undefined

Turn on [strict variables] mode if no [`Scope`] is to be provided for script evaluation runs.
This way, variable access errors are caught during compile time instead of runtime.