Statements
Statements are terminated by semicolons ;
and they are mandatory, except for the last statement
in a block (enclosed by {
… }
pairs) where it can be omitted.
Semicolons can also be omitted for statement types that always end in a block – for example
the if
, while
, for
, loop
and
switch
statements.
let a = 42; // normal assignment statement
let a = foo(42); // normal function call statement
foo < 42; // normal expression as statement
let a = { 40 + 2 }; // 'a' is set to the value of the statements block, which is the value of the last statement
// ^ the last statement does not require a terminating semicolon (but also works with it)
// ^ semicolon required here to terminate the 'let' statement
// it is a syntax error without it, even though it ends with '}'
// that is because the 'let' statement doesn't end in a block
if foo { a = 42 }
// ^ no need to terminate an if-statement with a semicolon
// that is because the 'if' statement ends in a block
4 * 10 + 2 // a statement which is just one expression - no ending semicolon is OK
// because it is the last statement of the whole block
Statements Block
Syntax
Statements blocks in Rhai are formed by enclosing zero or more statements within braces {
…}
.
{
statement;
statement;
… statement}
{
statement;
statement;
… statement;
}
// trailing semi-colon is optional
Closed scope
A statements block forms a closed scope.
Any variable and/or constant defined within the block are removed outside the block, so are modules imported within the block.
let x = 42;
let y = 18;
{
import "hello" as h;
const HELLO = 99;
let y = 0;
h::greet(); // ok
print(y + HELLO); // prints 99 (y is zero)
:
:
} // <- 'HELLO' and 'y' go away here...
print(x + y); // prints 60 (y is still 18)
print(HELLO); // <- error: 'HELLO' not found
h::greet(); // <- error: module 'h' not found
Statement Expression
A statement can be used anywhere where an expression is expected.
These are called, for lack of a more creative name, “statement expressions.”
The last statement of a statements block is always the block’s return value when used as a statement, regardless of whether it is terminated by a semicolon or not.
If the last statement has no return value (e.g. variable definitions, assignments) then it is
assumed to be ()
.
let x = {
let foo = calc_something();
let bar = foo + baz;
bar.further_processing(); // <- this is the return value
}; // <- semicolon is needed here...
// The above is equivalent to:
let result;
{
let foo = calc_something();
let bar = foo + baz;
result = bar.further_processing();
}
let x = result;
// Statement expressions can be inserted inside normal expressions
// to avoid duplicated calculations
let x = foo(bar) + { let v = calc(); process(v, v.len, v.abs) } + baz;
// The above is equivalent to:
let foo_result = foo(bar);
let calc_result;
{
let v = calc();
result = process(v, v.len, v.abs); // <- avoid calculating 'v'
}
let x = foo_result + calc_result + baz;
// Statement expressions are also useful as function call arguments
// when side effects are desired
do_work(x, y, { let z = foo(x, y); print(z); z });
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// statement expression