Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Function-like syntax for callable objects

API reference on docs.rs: callable, make_fn!.

callable gives one method of a user-owned trait the structural alias __priv_tmsbi_call. make_fn! can then bind any implementation and generate a same-name macro which forwards its arguments to that alias. No shared callable trait is imposed by this crate.

#[callable(apply)]
trait Action {
    fn apply(&self, point: usize) -> usize;
}

#[derive(Clone)]
struct Shift(usize);

impl Action for Shift {
    fn apply(&self, point: usize) -> usize {
        point + self.0
    }
}

impl Shift {
    fn inverse(&self) -> Shift {
        Shift(usize::MAX - self.0 + 1)
    }
}

make_fn!(sigma = Shift(3));

assert_eq!(sigma!(2), 5);
let _inverse = sigma.inverse();

The macro and value occupy different namespaces. Consequently sigma!(2) can expand to sigma.__priv_tmsbi_call(2) while ordinary methods remain available on sigma.

The generated alias is a default trait method. Existing implementations only implement the method selected by the attribute. Its receiver, arguments, generics, return type, bounds, and async or unsafe behavior are retained.

Mutable callable methods require a mutable binding:

#[callable(advance)]
trait Advance {
    fn advance(&mut self, amount: usize) -> usize;
}

struct Counter(usize);

impl Advance for Counter {
    fn advance(&mut self, amount: usize) -> usize {
        self.0 += amount;
        self.0
    }
}

make_fn!(mut counter = Counter(0));
assert_eq!(counter!(2), 2);
assert_eq!(counter!(3), 5);

make_fn! creates a let binding and is therefore intended for statement position inside a function or block. Method resolution must find exactly one accessible __priv_tmsbi_call; implementing multiple registered callable traits for one type deliberately makes the sugar ambiguous.