Implement capturing.
This commit is contained in:
@@ -54,7 +54,7 @@ WARNING - NOT Closures
|
||||
----------------------
|
||||
|
||||
Remember: anonymous functions, though having the same syntax as Rust _closures_, are themselves
|
||||
**not** closures. In particular, they do not capture their running environment. They are more like
|
||||
**not** closures. In particular, they do not capture their execution environment. They are more like
|
||||
Rust's function pointers.
|
||||
|
||||
They do, however, _capture_ variable _values_ from their execution environment, unless the [`no_capture`]
|
||||
|
62
doc/src/language/fn-capture.md
Normal file
62
doc/src/language/fn-capture.md
Normal file
@@ -0,0 +1,62 @@
|
||||
Capture The Calling Scope for Function Call
|
||||
==========================================
|
||||
|
||||
{{#include ../links.md}}
|
||||
|
||||
|
||||
Peeking Out of The Pure Box
|
||||
---------------------------
|
||||
|
||||
Rhai functions are _pure_, meaning that they depend on on their arguments and have no
|
||||
access to the calling environment.
|
||||
|
||||
When a function accesses a variable that is not defined within that function's scope,
|
||||
it raises an evaluation error.
|
||||
|
||||
It is possible, through a special syntax, to capture the calling scope - i.e. the scope
|
||||
that makes the function call - and access variables defined there.
|
||||
|
||||
```rust
|
||||
fn foo(y) { // function accesses 'x' and 'y', but 'x' is not defined
|
||||
x += y; // 'x' is modified in this function
|
||||
x
|
||||
}
|
||||
|
||||
let x = 1;
|
||||
|
||||
foo(41); // error: variable 'x' not found
|
||||
|
||||
// Calling a function with a '!' causes it to capture the calling scope
|
||||
|
||||
foo!(41) == 42; // the function can access the value of 'x', but cannot change it
|
||||
|
||||
x == 1; // 'x' is still the original value
|
||||
|
||||
x.method!(); // <- syntax error: capturing is not allowed in method-call style
|
||||
|
||||
// Capturing also works for function pointers
|
||||
|
||||
let f = Fn("foo");
|
||||
|
||||
call!(f, 41) == 42; // must use function-call style
|
||||
|
||||
f.call!(41); // <- syntax error: capturing is not allowed in method-call style
|
||||
```
|
||||
|
||||
|
||||
No Mutations
|
||||
------------
|
||||
|
||||
Variables in the calling scope are accessed as copies.
|
||||
Changes to them do not reflect back to the calling scope.
|
||||
|
||||
Rhai functions remain _pure_ in the sense that they can never mutate their environment.
|
||||
|
||||
|
||||
Caveat Emptor
|
||||
-------------
|
||||
|
||||
Functions relying on the calling scope is a _Very Bad Idea™_ because it makes code almost impossible
|
||||
to reason and maintain, as their behaviors are volatile and unpredictable.
|
||||
|
||||
This usage should be at the last resort.
|
@@ -1,6 +1,8 @@
|
||||
Capture External Variables via Automatic Currying
|
||||
================================================
|
||||
|
||||
{{#include ../links.md}}
|
||||
|
||||
Poor Man's Closures
|
||||
-------------------
|
||||
|
||||
|
@@ -33,7 +33,7 @@ curried.call(2) == 42; // <- de-sugars to 'func.call(21, 2)'
|
||||
Automatic Currying
|
||||
------------------
|
||||
|
||||
[Anonymous functions] defined via a closure syntax _capture_ external variables that are not shadowed inside
|
||||
the function's scope.
|
||||
[Anonymous functions] defined via a closure syntax _capture_ the _values_ of external variables
|
||||
that are not shadowed inside the function's scope.
|
||||
|
||||
This is accomplished via [automatic currying].
|
||||
|
Reference in New Issue
Block a user