diff --git a/doc/src/about/features.md b/doc/src/about/features.md index 45958e5a..5264f050 100644 --- a/doc/src/about/features.md +++ b/doc/src/about/features.md @@ -35,7 +35,7 @@ Dynamic * Organize code base with dynamically-loadable [modules]. -* [Function pointers]. +* Dynamic dispatch via [function pointers]. Safe ---- diff --git a/doc/src/appendix/keywords.md b/doc/src/appendix/keywords.md index 55299f22..85b9dc48 100644 --- a/doc/src/appendix/keywords.md +++ b/doc/src/appendix/keywords.md @@ -3,28 +3,30 @@ Keywords List {{#include ../links.md}} -| Keyword | Description | Not available under | -| :--------: | ------------------------------------- | ------------------- | -| `true` | Boolean true literal | | -| `false` | Boolean false literal | | -| `let` | Variable declaration | | -| `const` | Constant declaration | | -| `if` | If statement | | -| `else` | else block of if statement | | -| `while` | While loop | | -| `loop` | Infinite loop | | -| `for` | For loop | | -| `in` | Containment test, part of for loop | | -| `continue` | Continue a loop at the next iteration | | -| `break` | Loop breaking | | -| `return` | Return value | | -| `throw` | Throw exception | | -| `private` | Mark function private | [`no_function`] | -| `import` | Import module | [`no_module`] | -| `export` | Export variable | [`no_module`] | -| `as` | Alias for variable export | [`no_module`] | -| `fn` | Function definition | [`no_function`] | -| `type_of` | Get type name of value | | -| `print` | Print value | | -| `debug` | Print value in debug format | | -| `eval` | Evaluate script | | +| Keyword | Description | Not available under | +| :-------------------: | --------------------------------------- | ------------------- | +| `true` | Boolean true literal | | +| `false` | Boolean false literal | | +| `let` | Variable declaration | | +| `const` | Constant declaration | | +| `if` | If statement | | +| `else` | else block of if statement | | +| `while` | While loop | | +| `loop` | Infinite loop | | +| `for` | For loop | | +| `in` | Containment test, part of for loop | | +| `continue` | Continue a loop at the next iteration | | +| `break` | Loop breaking | | +| `return` | Return value | | +| `throw` | Throw exception | | +| `private` | Mark function private | [`no_function`] | +| `import` | Import module | [`no_module`] | +| `export` | Export variable | [`no_module`] | +| `as` | Alias for variable export | [`no_module`] | +| `fn` (lower-case `f`) | Function definition | [`no_function`] | +| `Fn` (capital `F`) | Function to create a [function pointer] | [`no_function`] | +| `call` | Call a [function pointer] | [`no_function`] | +| `type_of` | Get type name of value | | +| `print` | Print value | | +| `debug` | Print value in debug format | | +| `eval` | Evaluate script | | diff --git a/doc/src/language/fn-ptr.md b/doc/src/language/fn-ptr.md index fc083183..b509ca21 100644 --- a/doc/src/language/fn-ptr.md +++ b/doc/src/language/fn-ptr.md @@ -7,8 +7,8 @@ In fact, internally a function pointer simply stores the _name_ of the function Call a function pointer using the `call` method, which needs to be called in method-call style. -Built-in Functions ------------------- +Built-in methods +---------------- The following standard methods (mostly defined in the [`BasicFnPackage`]({{rootUrl}}/rust/packages.md) but excluded if using a [raw `Engine`]) operate on [strings]: @@ -54,3 +54,54 @@ let hello = Fn(fn_name + "_world"); hello.call(0); // error: function not found - "hello_world (i64)" ``` + + +Dynamic Dispatch +---------------- + +The purpose of function pointers is to enable rudimentary _dynamic dispatch_, meaning to determine, +at runtime, which function to call among a group. + +Although it is possible to simulate dynamic dispatch via a number and a large `if-then-else-if` statement, +using function pointers significantly simplifies the code. + +```rust +let x = some_calculation(); + +// These are the functions to call depending on the value of 'x' +fn method1(x) { ... } +fn method2(x) { ... } +fn method3(x) { ... } + +// Traditional - using decision variable +let func = sign(x); + +// Dispatch with if-statement +if func == -1 { + method1(42); +} else if func == 0 { + method2(42); +} else if func == 1 { + method3(42); +} + +// Using pure function pointer +let func = if x < 0 { + Fn("method1") +} else if x == 0 { + Fn("method2") +} else if x > 0 { + Fn("method3") +} + +// Dynamic dispatch +func.call(42); + +// Using functions map +let map = [ Fn("method1"), Fn("method2"), Fn("method3") ]; + +let func = sign(x) + 1; + +// Dynamic dispatch +map[func].call(42); +```