macro_rules! wrap_fn {
(0, $function:expr) => { ... };
(1, $function:expr) => { ... };
(2, $function:expr) => { ... };
(3, $function:expr) => { ... };
(4, $function:expr) => { ... };
(5, $function:expr) => { ... };
(6, $function:expr) => { ... };
(7, $function:expr) => { ... };
(8, $function:expr) => { ... };
(9, $function:expr) => { ... };
(10, $function:expr) => { ... };
($($ctx:ident,)? @arg $arity:expr => $($arg_name:ident),*; $function:expr) => { ... };
}
Expand description
An alternative for wrap
function which works for arguments / return results with
non-'static
lifetime.
The macro must be called with 2 arguments (in this order):
- Function arity (from 0 to 10 inclusive)
- Function or closure with the specified number of arguments. Using a function is recommended; using a closure may lead to hard-to-debug type inference errors.
As with wrap
, all function arguments must implement TryFromValue
and the return result
must implement IntoEvalResult
. Unlike wrap
, the arguments / return result do not
need to have a 'static
lifetime; examples include Value
s, Function
s
and EvalResult
s. Lifetimes of all arguments and the return result must match.
ยงExamples
fn is_function<T>(value: Value<'_, T>) -> bool {
value.is_function()
}
let program = "is_function(is_function) && !is_function(1)";
let program = Untyped::<F32Grammar>::parse_statements(program)?;
let module = Environment::new()
.insert_native_fn("is_function", wrap_fn!(1, is_function))
.compile_module("test", &program)?;
assert_eq!(module.run()?, Value::Bool(true));
Usage of lifetimes:
// Note that both `Value`s have the same lifetime due to elision.
fn take_if<T>(value: Value<'_, T>, condition: bool) -> Value<'_, T> {
if condition { value } else { Value::void() }
}
let program = "(1, 2).take_if(true) == (1, 2) && (3, 4).take_if(false) != (3, 4)";
let program = Untyped::<F32Grammar>::parse_statements(program)?;
let module = Environment::from_iter(Prelude.iter())
.insert_native_fn("take_if", wrap_fn!(2, take_if))
.compile_module("test_take_if", &program)?;
assert_eq!(module.run()?, Value::Bool(true));