This repository has been archived on 2025-08-04. You can view files and clone it, but cannot push or open issues or pull requests.
rhaj/_archive/rhai_engine/rhaibook/language/fn-anon.md
2025-04-04 08:28:07 +02:00

2.4 KiB
Raw Blame History

Anonymous Functions

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

Many functions in the standard API expect [function pointer] as parameters.

For example:

// Function 'double' defined here - used only once
fn double(x) { 2 * x }

// Function 'square' defined here - again used only once
fn square(x) { x * x }

let x = [1, 2, 3, 4, 5];

// Pass a function pointer to 'double'
let y = x.map(double);

// Pass a function pointer to 'square' using Fn(...) notation
let z = y.map(Fn("square"));

Sometimes it gets tedious to define separate [functions] only to dispatch them via single [function pointers] essentially, those [functions] are only ever called in one place.

This scenario is especially common when simulating object-oriented programming ([OOP]).

// Define functions one-by-one
fn obj_inc(x, y) { this.data += x * y; }
fn obj_dec(x) { this.data -= x; }
fn obj_print() { print(this.data); }

// Define object
let obj = #{
    data: 42,
    increment: obj_inc,     // use function pointers to
    decrement: obj_dec,     // refer to method functions
    print: obj_print
};

Syntax

Anonymous [functions] have a syntax similar to Rust's closures (they are not the same).

|param 1, param 2, ... , param n| statement

|param 1, param 2, ... , param n| { statements... }

No parameters:

|| statement

|| { statements... }

Anonymous functions can be disabled via [Engine::set_allow_anonymous_function][options].

Rewrite Using Anonymous Functions

The above can be rewritten using anonymous [functions].

let x = [1, 2, 3, 4, 5];

let y = x.map(|x| 2 * x);

let z = y.map(|x| x * x);

let obj = #{
    data: 42,
    increment: |x, y| this.data += x * y,   // one statement
    decrement: |x| this.data -= x,          // one statement
    print_obj: || {
        print(this.data);                   // full function body
    }
};

This de-sugars to:

// Automatically generated...
fn anon_fn_0001(x) { 2 * x }
fn anon_fn_0002(x) { x * x }
fn anon_fn_0003(x, y) { this.data += x * y; }
fn anon_fn_0004(x) { this.data -= x; }
fn anon_fn_0005() { print(this.data); }

let x = [1, 2, 3, 4, 5];

let y = x.map(anon_fn_0001);

let z = y.map(anon_fn_0002);

let obj = #{
    data: 42,
    increment: anon_fn_0003,
    decrement: anon_fn_0004,
    print: anon_fn_0005
};