Module functions

Source
Available on crate feature functions only.
Expand description

An abstraction over any function or closure.

The Function trait is used by the Engine::add_function method to abstract over a variety of function and closure types. This includes functions with variable argument types, return types and arity. When used as a filter the first argument to the function will always receive the piped value or expression. It can then have up to four more arguments. The renderer will check the number of arguments and the type of arguments when the function is used. Generally you should not try to implement any of the traits in this module yourself, instead you should define functions or closures that adhere to the generic implementation provided.

§Types

Function is implemented for functions and closures that take any owned argument implementing FunctionArg and any return type implementing FunctionReturn.

The first argument to the function (i.e. the piped expression when used as a filter) can also be specified using the following reference types. This is preferred in most cases because the renderer won’t have to clone the value before passing it to the function.

The second argument can be specified using the following reference types.

Other arguments can always use &str.

The technical reason for this contraint is that each permutation of reference arguments needs its own trait implementation.

§Examples

§Using existing functions

A lot of standard library functions and existing functions satisfy the Function trait, as long as they have the supported argument and return types.

let mut engine = upon::Engine::new();
engine.add_function("lower", str::to_lowercase);
engine.add_function("abs", i64::abs);
engine.add_function("eq", upon::Value::eq);

§Closures

Closures are perfectly valid functions, although often they will need type hints for the arguments.

let mut engine = upon::Engine::new();
engine.add_function("add", |a: i64, b: i64| a + b);

This could be use like this

{{ user.age | add: 10 }}

§Owned vs reference arguments

Consider the following template.

{{ users | last }}

Where the last function retrieves the final element in a list. We could implement this function taking an owned argument.

fn last(mut list: Vec<Value>) -> Option<Value> {
    list.pop()
}

But it would be more efficient to implement it such that it takes a slice, because then only the last element is cloned, as opposed to all the elements in the list being cloned.

fn last(list: &[Value]) -> Option<Value> {
    list.last().cloned()
}

Traits§

Function
Any function.
FunctionArg
An argument to a function.
FunctionArgs
The set of arguments to a function.
FunctionError
An error returned from a function.
FunctionReturn
A return value from a function.