2020-06-20 06:06:17 +02:00
|
|
|
Functions
|
|
|
|
=========
|
|
|
|
|
|
|
|
{{#include ../links.md}}
|
|
|
|
|
|
|
|
Rhai supports defining functions in script (unless disabled with [`no_function`]):
|
|
|
|
|
|
|
|
```rust
|
|
|
|
fn add(x, y) {
|
|
|
|
return x + y;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn sub(x, y,) { // trailing comma in parameters list is OK
|
|
|
|
return x - y;
|
|
|
|
}
|
|
|
|
|
|
|
|
print(add(2, 3)); // prints 5
|
|
|
|
print(sub(2, 3,)); // prints -1 - trailing comma in arguments list is OK
|
|
|
|
```
|
|
|
|
|
2020-06-21 18:03:45 +02:00
|
|
|
|
2020-06-20 06:06:17 +02:00
|
|
|
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.
|
|
|
|
|
|
|
|
```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
|
|
|
|
}
|
|
|
|
|
|
|
|
print(add(2, 3)); // prints 5
|
|
|
|
print(add2(42)); // prints 44
|
|
|
|
```
|
|
|
|
|
2020-06-21 18:03:45 +02:00
|
|
|
|
2020-06-20 06:06:17 +02:00
|
|
|
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.
|
|
|
|
|
|
|
|
```rust
|
|
|
|
let x = 42;
|
|
|
|
|
|
|
|
fn foo() { x } // <- syntax error: variable 'x' doesn't exist
|
|
|
|
```
|
|
|
|
|
2020-06-21 18:03:45 +02:00
|
|
|
|
2020-06-20 06:06:17 +02:00
|
|
|
Global Definitions Only
|
|
|
|
----------------------
|
|
|
|
|
|
|
|
Functions can only be defined at the global level, never inside a block or another function.
|
|
|
|
|
|
|
|
```rust
|
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2020-06-21 18:03:45 +02:00
|
|
|
|
|
|
|
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.
|
|
|
|
|
2020-06-22 16:02:49 +02:00
|
|
|
This is similar to Rust and many other modern languages, such as JavaScript's `function` keyword.
|
2020-06-26 04:39:18 +02:00
|
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
```rust
|
|
|
|
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.
|
|
|
|
|
|
|
|
```rust
|
|
|
|
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
|
|
|
|
```
|