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 Values, Functions and EvalResults. 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));