How to use a HashMap to store a struct method?

Hi there!

I want to use the HashMap object to collect callable objects. So I can call the callable objects dynamically.

Code below:

  1. main function:
fn main() {
    let mut id = ID::new();
    let mut machine = Machine::new("Rust", id.gen());
    machine.print();

    machine.add_operation("test", || { println!("Hello, machine"); });
    let test = machine.get_operation("test").unwrap();
    test();
}
  1. Machine structure:
struct Machine {
    name: String,
    id: u32,
    operations: HashMap<String, Arc<dyn Fn()>>,
}

impl Machine {
    fn new<T: Into<String>>(name: T, id: u32) -> Self {
        Self {
            name: name.into(),
            id,
            operations: HashMap::new(),
        }
    }
    
    fn print(&self) {
        println!("Machine<name: {}, id: {}>", self.name, self.id);
    }
    
    fn add_operation<F, T>(&mut self, name: T, f: F)
    where
        F: Fn() + 'static,
        T: Into<String>,
    {
        self.operations.insert(name.into(), Arc::new(f));
    }
    
    fn get_operation<T: Into<String>>(&self, name: T) -> Result<Arc<dyn Fn()>, &'static str> {
        let key = name.into();
        if let Some(op) = self.operations.get(&key) {
            Ok(Arc::clone(op))
        } else {
            Err("Unknown operation")
        }
    }
}
  1. ID structure:
struct ID(u32);

impl ID {
    fn new() -> Self {
        Self(0)
    }
    
    fn gen(&mut self) -> u32 {
        self.0 += 1;
        self.0
    }
}

Rust Playground

Now, I want to know how to store a method of Machine into operations?

// How could I add a method of struct into a hashmap belong the struct?
machine.add_operation("print", || { machine.print(); });
let print = machine.get_operation("print").unwrap();
print();

Thanks in advance. :smiley:

Well, machine.print() borrows the machine instance, so you can't then borrow it mutably at the same time, in order to add an operation. What you can do is pass in the reference to self explicitly: Playground.

1 Like

Thanks

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.