Hi there,
I would like to implement a method that takes a label and a closure and stores them in a way, so that the closure can be call once the label is chosen by a user. Could you tell me an elegant way to achieve this?
Thank you very much.
Hi there,
I would like to implement a method that takes a label and a closure and stores them in a way, so that the closure can be call once the label is chosen by a user. Could you tell me an elegant way to achieve this?
Thank you very much.
To store the closure, you need to box it. You'll probably want something like (untested):
struct MyContainer {
closures: BTreeMap<String, Box<Fn()>>,
}
impl MyContainer {
fn store<F: Fn() + 'static>(&mut self, label: String, function: F) {
self.closures.insert(label, Box::new(function) as Box<Fn()>);
}
fn call(&self, label: &str) {
// panics if no closure has been inserted with label.
(self.closures[label])();
}
}
Obviously, if you you might want some better error handling (and maybe allow closures return values).
Ah, that was quick, I was not aware of the +'static
syntax and got refused by the compiler on my approaches.
Thank you very much
If you want a slightly more flexible solution (where closures can reference the stack), you can use a custom lifetime:
struct MyContainer<'a> {
closures: BTreeMap<String, Box<Fn() + 'a>>,
}
impl<'a> MyContainer<'a> {
fn store<F: Fn() + 'a>(&mut self, label: String, function: F) {
self.closures.insert(label, Box::new(function) as Box<Fn() + 'a>);
}
fn call(&self, label: &str) {
// panics if no closure has been inserted with label.
(self.closures[label])();
}
}
F: Fn() + 'a
is short for F: Fn(), F: 'a
. The first constraint means "F
is a closure" and the second prevents F
from referencing variables on the stack that don't outlive the lifetime 'a
. Fn() + 'static
sets that lifetime to 'static
so it forbids closures from referencing anything on the stack.