Add dynamic dispatch.
This commit is contained in:
parent
580a62daaf
commit
259b6d0fcf
@ -35,7 +35,7 @@ Dynamic
|
|||||||
|
|
||||||
* Organize code base with dynamically-loadable [modules].
|
* Organize code base with dynamically-loadable [modules].
|
||||||
|
|
||||||
* [Function pointers].
|
* Dynamic dispatch via [function pointers].
|
||||||
|
|
||||||
Safe
|
Safe
|
||||||
----
|
----
|
||||||
|
@ -3,28 +3,30 @@ Keywords List
|
|||||||
|
|
||||||
{{#include ../links.md}}
|
{{#include ../links.md}}
|
||||||
|
|
||||||
| Keyword | Description | Not available under |
|
| Keyword | Description | Not available under |
|
||||||
| :--------: | ------------------------------------- | ------------------- |
|
| :-------------------: | --------------------------------------- | ------------------- |
|
||||||
| `true` | Boolean true literal | |
|
| `true` | Boolean true literal | |
|
||||||
| `false` | Boolean false literal | |
|
| `false` | Boolean false literal | |
|
||||||
| `let` | Variable declaration | |
|
| `let` | Variable declaration | |
|
||||||
| `const` | Constant declaration | |
|
| `const` | Constant declaration | |
|
||||||
| `if` | If statement | |
|
| `if` | If statement | |
|
||||||
| `else` | else block of if statement | |
|
| `else` | else block of if statement | |
|
||||||
| `while` | While loop | |
|
| `while` | While loop | |
|
||||||
| `loop` | Infinite loop | |
|
| `loop` | Infinite loop | |
|
||||||
| `for` | For loop | |
|
| `for` | For loop | |
|
||||||
| `in` | Containment test, part of for loop | |
|
| `in` | Containment test, part of for loop | |
|
||||||
| `continue` | Continue a loop at the next iteration | |
|
| `continue` | Continue a loop at the next iteration | |
|
||||||
| `break` | Loop breaking | |
|
| `break` | Loop breaking | |
|
||||||
| `return` | Return value | |
|
| `return` | Return value | |
|
||||||
| `throw` | Throw exception | |
|
| `throw` | Throw exception | |
|
||||||
| `private` | Mark function private | [`no_function`] |
|
| `private` | Mark function private | [`no_function`] |
|
||||||
| `import` | Import module | [`no_module`] |
|
| `import` | Import module | [`no_module`] |
|
||||||
| `export` | Export variable | [`no_module`] |
|
| `export` | Export variable | [`no_module`] |
|
||||||
| `as` | Alias for variable export | [`no_module`] |
|
| `as` | Alias for variable export | [`no_module`] |
|
||||||
| `fn` | Function definition | [`no_function`] |
|
| `fn` (lower-case `f`) | Function definition | [`no_function`] |
|
||||||
| `type_of` | Get type name of value | |
|
| `Fn` (capital `F`) | Function to create a [function pointer] | [`no_function`] |
|
||||||
| `print` | Print value | |
|
| `call` | Call a [function pointer] | [`no_function`] |
|
||||||
| `debug` | Print value in debug format | |
|
| `type_of` | Get type name of value | |
|
||||||
| `eval` | Evaluate script | |
|
| `print` | Print value | |
|
||||||
|
| `debug` | Print value in debug format | |
|
||||||
|
| `eval` | Evaluate script | |
|
||||||
|
@ -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.
|
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
|
The following standard methods (mostly defined in the [`BasicFnPackage`]({{rootUrl}}/rust/packages.md) but excluded if
|
||||||
using a [raw `Engine`]) operate on [strings]:
|
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)"
|
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);
|
||||||
|
```
|
||||||
|
Loading…
x
Reference in New Issue
Block a user