Macro arithmetic_eval::wrap_fn [−][src]
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));