Callback

How to implement callback.

Below is simple callback.

Fn, FnOnce

fn callback<F>(say: F, message: &str)
where
    // 👇 We use `FnOnce` here because...
    F: FnOnce(String), // 👈 We not mutate anything and call only once.
{
    // Just saying. 👇 `to_owned` or `to_string` can be use.
    say(message.to_owned());

    // 😱 uncomment to see scary error.
    // say(message.to_owned());
}

fn main() {
    // callback the say(message)
    callback(|msg| {
        println!("Say: {}", msg);
    }, "Hi!");
}

+ Copy

fn second_callback<F>(say: F, message: &str)
where
    F: FnOnce(String)
{
    say(message.to_owned());
}

fn callback<F>(say: F, message: &str)
where
    // 👇 We use `Fn` here because we will can it twice.
    F: Fn(String),

    // Or use `FnOnce` but copyable.
    // F: FnOnce(String) + std::marker::Copy,
{
    // Say Hi!
    say(message.to_owned());

    // Say Hey!
    second_callback(say, "Hey!");
}

fn main() {
    // callback the say(message)
    callback(|msg| {
        println!("Say: {}", msg);
    }, "Hi!");
}

🤔 Refer to : https://stackoverflow.com/questions/41081240/idiomatic-callbacks-in-rust

Now we will use struct to hold the callback.

1️⃣ "Function pointers": callbacks as fn

type Callback = fn();

struct Processor {
    callback: Callback,
}

impl Processor {
    fn set_callback(&mut self, c: Callback) {
        self.callback = c;
    }

    fn process_events(&self) {
        (self.callback)(); // 👈 Use parentheses to call the function.
    }
}

fn simple_callback() {
    println!("hello world!");
}

fn main() {
    let p = Processor {
        callback: simple_callback,
    };
    p.process_events(); // hello world!
}

Let's make it more generic.

2️⃣ Callbacks as generic function objects

struct Processor<CB> {
    callback: CB,
}

impl<CB> Processor<CB>
where
    // 👇 We use `FnMut` here because...
    CB: FnMut(), // 👈 `FnOnce` is call only once, `Fn` tend to readonly.
{
    fn set_callback(&mut self, c: CB) {
        self.callback = c;
    }

    // This mutating self 👇 because `FnMut`
    fn process_events(&mut self) {
        (self.callback)();
    }
}

fn main() {
    let s = "world!".to_string();
    let callback = || println!("hello {}", s);
    let mut p = Processor { callback };
    p.process_events();
}

It's generic but callback is not, let's go deeper.

3️⃣ Non-generic callbacks: function trait objects

struct Processor {
    // We put previous `FnMut` into the `Box`
    callback: Box<dyn FnMut()>, // And `dyn` for more dynamic fn.
}

impl Processor {
    // We will need lifetime bound on the type here 👇
    fn set_callback(&mut self, c: impl FnMut() + 'static) {
        self.callback = Box::new(c);
    }

    fn process_events(&mut self) {
        (self.callback)();
    }
}

fn simple_callback() {
    println!("hello");
}

fn main() {
    let mut p = Processor {
        callback: Box::new(simple_callback),
    };
    p.process_events();
    let s = "world!".to_string();
    let callback2 = move || println!("hello {}", s);
    p.set_callback(callback2);
    p.process_events();
}

Nicer but 'static is too much, let's fix it.

4️⃣ Lifetime of references inside boxed closures

// Now we use `'a` 👇 here instead.
struct Processor<'a> {
    callback: Box<dyn FnMut() + 'a>, // 👈 Also here
}

// Now 👇 this look messy (for good)
impl<'a> Processor<'a> {
    fn set_callback(&mut self, c: impl FnMut() + 'a) {// 👈 Also here
        self.callback = Box::new(c);
    }

    fn process_events(&mut self) {
        (self.callback)();
    }
}

fn simple_callback() {
    println!("hello");
}

fn main() {
    let mut p = Processor {
        callback: Box::new(simple_callback),
    };
    p.process_events();
    let s = "world!".to_string();
    let callback2 = move || println!("hello {}", s);
    p.set_callback(callback2);
    p.process_events();
}