Change call_fn_dynamic to accept any type that is IntoIterator<Item=Dynamic>.
This commit is contained in:
parent
5275778952
commit
b24fdd7a4d
26
README.md
26
README.md
@ -359,16 +359,14 @@ let result: i64 = engine.call_fn(&mut scope, &ast, "hello", () )?;
|
||||
let result: () = engine.call_fn(&mut scope, &ast, "hidden", ())?;
|
||||
```
|
||||
|
||||
For more control, construct all arguments as `Dynamic` values and use `Engine::call_fn_dynamic`:
|
||||
For more control, construct all arguments as `Dynamic` values and use `Engine::call_fn_dynamic`, passing it
|
||||
anything that implements `IntoIterator<Item = Dynamic>` (such as a simple `Vec<Dynamic>`):
|
||||
|
||||
```rust
|
||||
let result: Dynamic = engine.call_fn_dynamic(&mut scope, &ast, "hello",
|
||||
&mut [ String::from("abc").into(), 123_i64.into() ])?;
|
||||
vec![ String::from("abc").into(), 123_i64.into() ])?;
|
||||
```
|
||||
|
||||
However, beware that `Engine::call_fn_dynamic` _consumes_ its arguments, meaning that all arguments passed to it
|
||||
will be replaced by `()` afterwards. To re-use the arguments, clone them beforehand and pass in the clone.
|
||||
|
||||
### Creating Rust anonymous functions from Rhai script
|
||||
|
||||
[`Func`]: #creating-rust-anonymous-functions-from-rhai-script
|
||||
@ -738,7 +736,7 @@ use rhai::Dynamic;
|
||||
|
||||
let x = (42_i64).into(); // 'into()' works for standard types
|
||||
|
||||
let y = Dynamic::from(String::from("hello!")); // remember &str is not supported by Rhai
|
||||
let y = Dynamic::from("hello!".to_string()); // remember &str is not supported by Rhai
|
||||
```
|
||||
|
||||
Functions registered with the [`Engine`] can be _overloaded_ as long as the _signature_ is unique,
|
||||
@ -1124,14 +1122,14 @@ not available under [`no_index`].
|
||||
To use custom types for `print` and `debug`, or convert its value into a [string], it is necessary that the following
|
||||
functions be registered (assuming the custom type is `T : Display + Debug`):
|
||||
|
||||
| Function | Signature | Typical implementation | Usage |
|
||||
| ----------- | ------------------------------------------------ | ------------------------------ | --------------------------------------------------------------------------------------- |
|
||||
| `to_string` | `|s: &mut T| -> String` | `s.to_string()` | Converts the custom type into a [string] |
|
||||
| `print` | `|s: &mut T| -> String` | `s.to_string()` | Converts the custom type into a [string] for the [`print`](#print-and-debug) statement |
|
||||
| `debug` | `|s: &mut T| -> String` | `format!("{:?}", s)` | Converts the custom type into a [string] for the [`debug`](#print-and-debug) statement |
|
||||
| `+` | `|s1: ImmutableString, s: T| -> ImmutableString` | `s1 + s` | Append the custom type to another [string], for `print("Answer: " + type);` usage |
|
||||
| `+` | `|s: T, s2: ImmutableString| -> String` | `s.to_string().push_str(&s2);` | Append another [string] to the custom type, for `print(type + " is the answer");` usage |
|
||||
| `+=` | `|s1: &mut ImmutableString, s: T|` | `s1 += s.to_string()` | Append the custom type to an existing [string], for `s += type;` usage |
|
||||
| Function | Signature | Typical implementation | Usage |
|
||||
| ----------- | ------------------------------------------------ | ------------------------------------- | --------------------------------------------------------------------------------------- |
|
||||
| `to_string` | `|s: &mut T| -> ImmutableString` | `s.to_string().into()` | Converts the custom type into a [string] |
|
||||
| `print` | `|s: &mut T| -> ImmutableString` | `s.to_string().into()` | Converts the custom type into a [string] for the [`print`](#print-and-debug) statement |
|
||||
| `debug` | `|s: &mut T| -> ImmutableString` | `format!("{:?}", s).into()` | Converts the custom type into a [string] for the [`debug`](#print-and-debug) statement |
|
||||
| `+` | `|s1: ImmutableString, s: T| -> ImmutableString` | `s1 + s` | Append the custom type to another [string], for `print("Answer: " + type);` usage |
|
||||
| `+` | `|s: T, s2: ImmutableString| -> ImmutableString` | `s.to_string().push_str(&s2).into();` | Append another [string] to the custom type, for `print(type + " is the answer");` usage |
|
||||
| `+=` | `|s1: &mut ImmutableString, s: T|` | `s1 += s.to_string()` | Append the custom type to an existing [string], for `s += type;` usage |
|
||||
|
||||
`Scope` - Initializing and maintaining state
|
||||
-------------------------------------------
|
||||
|
@ -14,6 +14,7 @@ Breaking changes
|
||||
* `Engine::register_indexer` is renamed to `Engine::register_indexer_get`.
|
||||
* `Module::set_indexer_fn` is renamed to `Module::set_indexer_get_fn`.
|
||||
* The tuple `ParseError` now exposes the internal fields and the `ParseError::error_type` and `ParseError::position` methods are removed. The first tuple field is the `ParseErrorType` and the second tuple field is the `Position`.
|
||||
* `Engine::call_fn_dynamic` now takes any type that implements `IntoIterator<Item = Dynamic>`.
|
||||
|
||||
New features
|
||||
------------
|
||||
|
34
src/api.rs
34
src/api.rs
@ -1114,7 +1114,7 @@ impl Engine {
|
||||
args: A,
|
||||
) -> Result<T, Box<EvalAltResult>> {
|
||||
let mut arg_values = args.into_vec();
|
||||
let result = self.call_fn_dynamic(scope, ast, name, arg_values.as_mut())?;
|
||||
let result = self.call_fn_dynamic_raw(scope, ast, name, arg_values.as_mut())?;
|
||||
|
||||
let return_type = self.map_type_name(result.type_name());
|
||||
|
||||
@ -1128,13 +1128,6 @@ impl Engine {
|
||||
|
||||
/// Call a script function defined in an `AST` with multiple `Dynamic` arguments.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// All the arguments are _consumed_, meaning that they're replaced by `()`.
|
||||
/// This is to avoid unnecessarily cloning the arguments.
|
||||
/// Do you use the arguments after this call. If you need them afterwards,
|
||||
/// clone them _before_ calling this function.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
@ -1155,13 +1148,13 @@ impl Engine {
|
||||
/// scope.push("foo", 42_i64);
|
||||
///
|
||||
/// // Call the script-defined function
|
||||
/// let result = engine.call_fn_dynamic(&mut scope, &ast, "add", &mut [ String::from("abc").into(), 123_i64.into() ])?;
|
||||
/// let result = engine.call_fn_dynamic(&mut scope, &ast, "add", vec![ String::from("abc").into(), 123_i64.into() ])?;
|
||||
/// assert_eq!(result.cast::<i64>(), 168);
|
||||
///
|
||||
/// let result = engine.call_fn_dynamic(&mut scope, &ast, "add1", &mut [ String::from("abc").into() ])?;
|
||||
/// let result = engine.call_fn_dynamic(&mut scope, &ast, "add1", vec![ String::from("abc").into() ])?;
|
||||
/// assert_eq!(result.cast::<i64>(), 46);
|
||||
///
|
||||
/// let result= engine.call_fn_dynamic(&mut scope, &ast, "bar", &mut [])?;
|
||||
/// let result= engine.call_fn_dynamic(&mut scope, &ast, "bar", vec![])?;
|
||||
/// assert_eq!(result.cast::<i64>(), 21);
|
||||
/// # }
|
||||
/// # Ok(())
|
||||
@ -1169,6 +1162,25 @@ impl Engine {
|
||||
/// ```
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
pub fn call_fn_dynamic(
|
||||
&self,
|
||||
scope: &mut Scope,
|
||||
ast: &AST,
|
||||
name: &str,
|
||||
arg_values: impl IntoIterator<Item = Dynamic>,
|
||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
let mut arg_values: StaticVec<_> = arg_values.into_iter().collect();
|
||||
self.call_fn_dynamic_raw(scope, ast, name, arg_values.as_mut())
|
||||
}
|
||||
|
||||
/// Call a script function defined in an `AST` with multiple `Dynamic` arguments.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// All the arguments are _consumed_, meaning that they're replaced by `()`.
|
||||
/// This is to avoid unnecessarily cloning the arguments.
|
||||
/// Do not use the arguments after this call. If they are needed afterwards,
|
||||
/// clone them _before_ calling this function.
|
||||
pub(crate) fn call_fn_dynamic_raw(
|
||||
&self,
|
||||
scope: &mut Scope,
|
||||
ast: &AST,
|
||||
|
@ -216,6 +216,15 @@ impl<T> FromIterator<T> for StaticVec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> IntoIterator for StaticVec<T> {
|
||||
type Item = T;
|
||||
type IntoIter = Box<dyn Iterator<Item = T>>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> StaticVec<T> {
|
||||
/// Create a new `StaticVec`.
|
||||
#[inline(always)]
|
||||
|
Loading…
Reference in New Issue
Block a user