Сохранение функции в хэш-карте

#rust

#Ржавчина

Вопрос:

Я хочу сохранить функцию внутри Hashmap в rust, но я не знаю, как «получить» ее и вызвать в другом месте. Вот что я пробовал

 type Ihello = fn() -> String;


fn main() {
    use std::collections::HashMap;
    let mut mapp: HashMap<String, Ihello> = HashMap::new();
    mapp.insert(
        "hello".to_string(),
        hello
    );
    let hello_string = "hello".to_string();
    let hello: Option<amp;Ihello> = book_reviews.get(amp;hello_string);
    
}

fn hello() -> String {
    String::from("HELLOHELLOHELLO")
}
 

Я хочу позже «вызвать» функцию hello, есть ли какой-нибудь способ это сделать?
или есть альтернативный способ сделать это?

Ответ №1:

HashMap.get возвращает Option<amp;Ihello> , что означает, что результатом может быть либо Some значение Ihello , либо None (если ключ не существует). Итак, одним из решений является разрушение оператора Option if let using.

 let hello: Option<amp;Ihello> = mapp.get(amp;hello_string);
if let Some(val) = hello {
    println!("{}", val()); // calling the function here
} else {
    println!("Key is missing!");
}
 

Ответ №2:

Вы можете использовать a Box для хранения ссылки на функцию, а затем вызвать функцию, которую map.get(...).unwrap() возвращает (обратите внимание, что у нас есть ()() в последней строке).

 use std::collections::HashMap;

type Ihello = dyn Fn() -> String;

fn hello() -> String {
    "HELLO".to_string()
}

fn main() {
    let mut map: HashMap<amp;str, Box<Ihello>> = HashMap::new();
    
    map.insert("hello", Box::new(hello));
    
    println!("{}", map.get("hello").unwrap()());
}
 

Комментарии:

1. Боксирование признака Fn поможет сохранить замыкания в HashMap (в дополнение к обычным функциям), но поскольку это не проблема пользователя, это кажется отвлекающим фактором.

2. @hkBst согласился, но стоит отметить, что fn() -> String это будет поддерживать только функции, в то время как что-то вроде Box<dyn FnMut() -> String> также поддерживает замыкания. На самом деле, ИМХО, последнее здесь более уместно.