rhai/doc/src/language/functions.md
2020-07-08 09:48:25 +08:00

3.1 KiB

Functions

{{#include ../links.md}}

Rhai supports defining functions in script (unless disabled with [no_function]):

fn add(x, y) {
    return x + y;
}

fn sub(x, y,) {     // trailing comma in parameters list is OK
    return x - y;
}

add(2, 3) == 5;

sub(2, 3,) == -1;  // trailing comma in arguments list is OK

Implicit Return

Just like in Rust, an implicit return can be used. In fact, the last statement of a block is always the block's return value regardless of whether it is terminated with a semicolon ';'. This is different from Rust.

fn add(x, y) {      // implicit return:
    x + y;          // value of the last statement (no need for ending semicolon)
                    // is used as the return value
}

fn add2(x) {
    return x + 2;   // explicit return
}

add(2, 3) == 5;

add2(42) == 44;

No Access to External Scope

Functions are not closures. They do not capture the calling environment and can only access their own parameters. They cannot access variables external to the function itself.

let x = 42;

fn foo() { x }      // <- syntax error: variable 'x' doesn't exist

Global Definitions Only

Functions can only be defined at the global level, never inside a block or another function.

// Global level is OK
fn add(x, y) {
    x + y
}

// The following will not compile
fn do_addition(x) {
    fn add_y(n) {   // <- syntax error: functions cannot be defined inside another function
        n + y
    }

    add_y(x)
}

Use Before Definition

Unlike C/C++, functions in Rhai can be defined anywhere at global level. A function does not need to be defined prior to being used in a script; a statement in the script can freely call a function defined afterwards.

This is similar to Rust and many other modern languages, such as JavaScript's function keyword.

Arguments Passed by Value

Functions defined in script always take [Dynamic] parameters (i.e. the parameter can be of any type). Therefore, functions with the same name and same number of parameters are equivalent.

It is important to remember that all arguments are passed by value, so all Rhai script-defined functions are pure (i.e. they never modify their arguments). Any update to an argument will not be reflected back to the caller.

fn change(s) {      // 's' is passed by value
    s = 42;         // only a COPY of 's' is changed
}

let x = 500;

change(x);

x == 500;           // 'x' is NOT changed!

this - Simulating an Object Method

Functions can also be called in method-call style. When this is the case, the keyword 'this' binds to the object in the method call and can be changed.

fn change() {       // not that the object does not need a parameter
    this = 42;      // 'this' binds to the object in method-call
}

let x = 500;

x.change();         // call 'change' in method-call style, 'this' binds to 'x'

x == 42;            // 'x' is changed!

change();           // <- error: `this` is unbounded