Почему статическая хеш-карта для функции запоминания не может быть заимствована как изменяемая? - PullRequest
0 голосов
/ 14 ноября 2018

Я пытаюсь создать функцию памятки в Rust.Проблема возникает при получении изменяемой ссылки для кеша HashMap.Я все еще не уверен в системе типов и немного борюсь.

use std::collections::HashMap;
use std::hash::Hash;

fn memoize<A, B, F>(f: F, cache: &'static HashMap<A, B>) -> impl Fn(A) -> B
where
    A: Eq + Hash + Copy,
    B: Clone,
    F: Fn(A) -> B,
{
    move |value: A| {
        if !cache.contains_key(&value) {
            cache.insert(value, f(value.clone()));
        }
        let res = cache.get(&value).unwrap();
        res.clone()
    }
}

Ошибка:

error[E0596]: cannot borrow immutable borrowed content `**cache` as mutable
  --> src/lib.rs:12:13
   |
12 |             cache.insert(value, f(value.clone()));
   |             ^^^^^ cannot borrow as mutable

Почему статический параметр времени жизни не может быть изменяемым?

1 Ответ

0 голосов
/ 14 ноября 2018

Переменная является неизменной по умолчанию в Rust, поэтому вы не можете изменить переменную, которая не объявлена ​​как mut.'static время жизни не влияет на изменчивость, а только на то, как долго живёт переменная.

A Fn "[...]может вызываться повторно без изменения состояния. ".И именно здесь проблема.Вы хотите изменить среду (в данном случае ваш HashMap).

Вы должны использовать FnMut, чтобы иметь возможность изменять среду.

Если вы используете Entry API , вы можете упростить свой код:

use std::collections::HashMap;
use std::hash::Hash;

fn memoize<A, B, F>(f: F, cache: &'static mut HashMap<A, B>) -> impl FnMut(A) -> B
where
    A: Eq + Hash + Copy,
    B: Clone,
    F: Fn(A) -> B,
{
    move |value: A| {
        let res = cache.entry(value).or_insert_with(|| f(value));
        res.clone()
    }
}

В качестве идентификатора, если вы компилируете свой код с #[feature(nll)], сообщение об ошибке на самом деле очень хорошее.

error[E0596]: cannot borrow `*cache` as mutable, as `Fn` closures cannot mutate their captured variables
  --> src/lib.rs:14:13
   |
14 |             cache.insert(value, f(value.clone()));
   |             ^^^^^ cannot borrow as mutable
   |
help: consider changing this to accept closures that implement `FnMut`
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...