Refine docs.
This commit is contained in:
@@ -9,11 +9,11 @@ Usage Scenario
|
||||
|
||||
* A system where settings and configurations are complex and logic-driven.
|
||||
|
||||
* Where it is not possible to configure said system via standard configuration file formats such as `TOML` or `YAML`.
|
||||
* Where said system is too complex to configure via standard configuration file formats such as `JSON`, `TOML` or `YAML`.
|
||||
|
||||
* The system configuration is complex enough that it requires a full programming language. Essentially _configuration by code_.
|
||||
* The system is complex enough to require a full programming language to configure. Essentially _configuration by code_.
|
||||
|
||||
* Yet the configurations must be flexible, late-bound and dynamically loadable, just like a configuration file.
|
||||
* Yet the configuration must be flexible, late-bound and dynamically loadable, just like a configuration file.
|
||||
|
||||
|
||||
Key Concepts
|
||||
@@ -23,6 +23,8 @@ Key Concepts
|
||||
|
||||
* Expose the configuration API. Use separate scripts to configure that API. Dynamically load scripts via the `import` statement.
|
||||
|
||||
* Leverage [function overloading] to simplify the API design.
|
||||
|
||||
* Since Rhai is _sand-boxed_, it cannot mutate the environment. To modify the external configuration object via an API, it must be wrapped in a `RefCell` (or `RwLock`/`Mutex` for [`sync`]) and shared to the [`Engine`].
|
||||
|
||||
|
||||
|
@@ -19,12 +19,26 @@ Key Concepts
|
||||
|
||||
* Expose a Control API.
|
||||
|
||||
* Since Rhai is _sand-boxed_, it cannot mutate the environment. To perform external actions via an API, the actual system must be wrapped in a `RefCell` (or `RwLock`/`Mutex` for [`sync`]) and shared to the [`Engine`].
|
||||
* Leverage [function overloading] to simplify the API design.
|
||||
|
||||
* Since Rhai is _[sand-boxed]_, it cannot mutate the environment. To perform external actions via an API, the actual system must be wrapped in a `RefCell` (or `RwLock`/`Mutex` for [`sync`]) and shared to the [`Engine`].
|
||||
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
There are two broad ways for Rhai to control an external system, both of which involve
|
||||
wrapping the system in a shared, interior-mutated object.
|
||||
|
||||
This is one way which does not involve exposing the data structures of the external system,
|
||||
but only through exposing an abstract API primarily made up of functions.
|
||||
|
||||
Use this when the API is relatively simple and clean, and the number of functions is small enough.
|
||||
|
||||
For a complex API involving lots of functions, or an API that is object-based,
|
||||
use the [Singleton Command Object]({{rootUrl}}/patterns/singleton.md) pattern instead.
|
||||
|
||||
|
||||
### Functional API
|
||||
|
||||
Assume that a system provides the following functional API:
|
||||
|
@@ -4,6 +4,4 @@ Advanced Patterns
|
||||
{{#include ../links.md}}
|
||||
|
||||
|
||||
Use Rhai in different scenarios other than simply evaluating a user script.
|
||||
|
||||
These patterns are useful when Rhai needs to affect/control the external environment.
|
||||
Leverage the full power and flexibility of Rhai in advanced scenarios.
|
||||
|
@@ -18,17 +18,17 @@ Rhai's [object maps] has [special support for OOP]({{rootUrl}}/language/object-m
|
||||
| [Object map] properties that hold [function pointers] | methods |
|
||||
|
||||
When a property of an [object map] is called like a method function, and if it happens to hold
|
||||
a valid [function pointer] (perhaps defined via an [anonymous function]), then the call will be
|
||||
dispatched to the actual function with `this` binding to the [object map] itself.
|
||||
a valid [function pointer] (perhaps defined via an [anonymous function] or more commonly as a [closure]),
|
||||
then the call will be dispatched to the actual function with `this` binding to the [object map] itself.
|
||||
|
||||
|
||||
Use Anonymous Functions to Define Methods
|
||||
----------------------------------------
|
||||
|
||||
[Anonymous functions] defined as values for [object map] properties take on a syntactic shape
|
||||
that resembles very closely that of class methods in an OOP language.
|
||||
[Anonymous functions] or [closures] defined as values for [object map] properties take on
|
||||
a syntactic shape that resembles very closely that of class methods in an OOP language.
|
||||
|
||||
Anonymous functions can also _capture_ variables from the defining environment, which is a very
|
||||
Closures also _[capture][automatic currying]_ variables from the defining environment, which is a very
|
||||
common OOP pattern. Capturing is accomplished via a feature called _[automatic currying]_ and
|
||||
can be turned off via the [`no_closure`] feature.
|
||||
|
||||
@@ -40,23 +40,22 @@ Examples
|
||||
let factor = 1;
|
||||
|
||||
// Define the object
|
||||
let obj =
|
||||
#{
|
||||
data: 0,
|
||||
increment: |x| this.data += x, // 'this' binds to 'obj'
|
||||
update: |x| this.data = x * factor, // 'this' binds to 'obj', 'factor' is captured
|
||||
action: || print(this.data) // 'this' binds to 'obj'
|
||||
};
|
||||
let obj = #{
|
||||
data: 0, // object field
|
||||
increment: |x| this.data += x, // 'this' binds to 'obj'
|
||||
update: |x| this.data = x * factor, // 'this' binds to 'obj', 'factor' is captured
|
||||
action: || print(this.data) // 'this' binds to 'obj'
|
||||
};
|
||||
|
||||
// Use the object
|
||||
obj.increment(1);
|
||||
obj.action(); // prints 1
|
||||
obj.action(); // prints 1
|
||||
|
||||
obj.update(42);
|
||||
obj.action(); // prints 42
|
||||
obj.action(); // prints 42
|
||||
|
||||
factor = 2;
|
||||
|
||||
obj.update(42);
|
||||
obj.action(); // prints 84
|
||||
obj.action(); // prints 84
|
||||
```
|
||||
|
@@ -1,5 +1,5 @@
|
||||
Singleton Command Objects
|
||||
========================
|
||||
Singleton Command Object
|
||||
=======================
|
||||
|
||||
{{#include ../links.md}}
|
||||
|
||||
@@ -21,9 +21,11 @@ Usage Scenario
|
||||
Key Concepts
|
||||
------------
|
||||
|
||||
* Expose a Command type with an API.
|
||||
* Expose a Command type with an API. The [`no_object`] feature must not be on.
|
||||
|
||||
* Since Rhai is _sand-boxed_, it cannot mutate the environment. To perform external actions via an API, the command object type must be wrapped in a `RefCell` (or `RwLock`/`Mutex` for [`sync`]) and shared to the [`Engine`].
|
||||
* Leverage [function overloading] to simplify the API design.
|
||||
|
||||
* Since Rhai is _[sand-boxed]_, it cannot mutate the environment. To perform external actions via an API, the command object type must be wrapped in a `RefCell` (or `RwLock`/`Mutex` for [`sync`]) and shared to the [`Engine`].
|
||||
|
||||
* Load each command object into a custom [`Scope`] as constant variables.
|
||||
|
||||
@@ -33,6 +35,18 @@ Key Concepts
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
There are two broad ways for Rhai to control an external system, both of which involve
|
||||
wrapping the system in a shared, interior-mutated object.
|
||||
|
||||
This is the other way which involves directly exposing the data structures of the external system
|
||||
as a name singleton object in the scripting space.
|
||||
|
||||
Use this when the API is complex and clearly object-based.
|
||||
|
||||
For a relatively simple API that is action-based and not object-based,
|
||||
use the [Control Layer]({{rootUrl}}/patterns/control.md) pattern instead.
|
||||
|
||||
|
||||
### Functional API
|
||||
|
||||
Assume the following command object type:
|
||||
|
Reference in New Issue
Block a user