Skip to main content

closure

Macro closure 

Source
macro_rules! closure {
    ($($argument_type:tt)*) => { ... };
}
Expand description

Creates an anonymous Fn-, FnMut-, or FnOnce-like closure whose call method may be generic.

§Quick guide

First declare the interface with closure_trait!, then repeat that trait’s receiver, generic bounds, arguments, and output in the closure! call:

closure!(
    captures,
    Trait<T: Bounds>(&mut self, first: T, second: T) -> Output
    where Provider: Provides<T>
    { body }
)

Captures are optional. The result is an anonymous value implementing Trait; invoke it with call, call_mut, or call_once as permitted by the receiver declared for that trait. The default alloc feature additionally provides call_box.

Capture declarations precede the trait and method signature:

  • &x: Type or &mut x: Type borrows x at construction;
  • x: Type or mut x: Type moves x into the closure;
  • clone x: Type or clone mut x: Type clones x at construction;
  • x: &'closure Type or x: &'closure mut Type stores an existing reference.

The receiver selects the call mode. An omitted receiver, or &self, creates an Fn-like implementation. &mut self creates an FnMut-like implementation, and self creates an FnOnce-like implementation. Mutable owned captures must opt in with mut; &mut captures are already explicitly mutable. Call arguments use name: Type syntax and may be omitted or repeated; a trailing comma is accepted. A capture may not have the same name as a call argument. Any generic where clause declared by closure_trait! is repeated before the body.

Every capture requires an explicit type and a trailing comma. The macro-provided 'closure lifetime may occur anywhere in a capture type. Omitting -> Output means -> ().

use generic_closure::{closure, closure_trait};
use std::fmt::Display;

closure_trait!(Render<T: Display>(value: T) -> String);

let prefix = String::from("value: ");
let suffix = String::from("!");
let render = closure!(
    clone prefix: String,
    suffix: String,
    Render<T: Display>(value: T) -> String {
        format!("{prefix}{value}{suffix}")
    }
);

assert_eq!(prefix, "value: ");
assert_eq!(render.call(42), "value: 42!");
assert_eq!(render.call("hello"), "value: hello!");