How to store closure in HashMap

I have a struct:

pub struct MyStruct<'a> {
    keys: HashMap<&'a str, &'a dyn Fn() -> ()>,
    file:File
}

impl<'a> MyStruct<'a> {
    pub fn add_key(&mut self, path: &'a str, func: &'a dyn Fn() -> ()) {
        self.keys.entry(path).or_insert(func);
    }

  pub fn get(&mut self){
...
         }

  pub fn if_key(&self, key: &str) -> Result<&str, &str> {
        for k in &self.keys {
            if k.0 == &key {
                k.1();
                return Ok("...");
            }
        }

        Err("...")
    }

}

when I run it:

fn main(){
let x=MyStruct::new();

 let cl: &dyn Fn() -> () = &|| {
        match x.get() {
            Ok(o) => println!("{}", o),
            Err(e) => println!("{}", e),
      
    };
    };

file.add_key("...", cl);
}

I get a Error because I have ref and mut ref to same data.

How can I fix it?

When you're storing a bunch of values in a HashMap or another collection for a while, usually you want them to be owned types like String and Box<dyn Fn()> instead of borrowed types like &'a str and &'a dyn Fn(). Making this change might fix some of the lifetime errors you're running into.

Also, instead of iterating through every entry of self.keys, you can use get() to only look up the key you need. Rust Playground:

use std::collections::HashMap;

pub struct FileDes {
    keys: HashMap<String, Box<dyn Fn() -> ()>>,
}

impl FileDes {
    pub fn add_key(&mut self, path: String, func: Box<dyn Fn() -> ()>) {
        self.keys.entry(path).or_insert(func);
    }

    pub fn if_key(&self, key: &str) -> Result<&str, &str> {
        if let Some(func) = self.keys.get(key) {
            func();
            return Ok("...");
        }

        Err("...")
    }
}
3 Likes

Your example code does not reproduce this error. It doesn't compile due to some fairly trivial syntax errors (e.g. your type and variable names seem to be inconsistent, mutability is wrong, etc.). If you fix those, there are no lifetime-related errors or even warnings.

1 Like

I corrected my example

I changed my closure:

 let cl: Box<dyn Fn(&MyStruct) -> (slf)> = Box::new(|slf| {
        match slf.get() {
            Ok(o) => println!("{}", o),
            Err(e) => println!("{}", e),
      
    });

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.