Время жизни в HashMap, где ключ относится к значению - PullRequest
0 голосов
/ 04 апреля 2020

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

[derive(Debug)]
struct Foo {
    id: u32,
    name: String,
}
let foos = vec![
    Foo { id: 1, name: "Bill".to_string() },
    Foo { id: 2, name: "Mary".to_string() },
];
println!("{:?}", foos);
println!("{:?}", map_by(foos.iter(), |f|  f.id));  // borrow  the Foos
println!("{:?}", map_by(foos.iter(), |f| &f.name));          // borrow
println!("{:?}", map_by(foos.iter(), |f|  f.name.as_str())); // borrow
println!("{:?}", map_by(foos,        |f|  f.id));  // consume the Foos

Я написал это, и это работает для вышеуказанного использования:

fn map_by<I,K,V>(iterable: I, f: impl Fn(&V) -> K) -> HashMap<K,V>
where I: IntoIterator<Item = V>,
      K: Eq + Hash
{
    iterable.into_iter().map(|v| (f(&v), v)).collect()
}

[Foo { id: 1, name: "Bill" }, Foo { id: 2, name: "Mary" }]
{1: Foo { id: 1, name: "Bill" }, 2: Foo { id: 2, name: "Mary" }}
{"Bill": Foo { id: 1, name: "Bill" }, "Mary": Foo { id: 2, name: "Mary" }}
{"Bill": Foo { id: 1, name: "Bill" }, "Mary": Foo { id: 2, name: "Mary" }}
{2: Foo { id: 2, name: "Mary" }, 1: Foo { id: 1, name: "Bill" }}

Отлично! Но это не работает, когда я позволяю HashMap СОБСТВЕННО значениям, когда ключи ссылаются на них:

println!("{:?}", map_by(foos,        |f| f.name.as_str()));

error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements

И, к сожалению, сообщение об ошибке растопило мой мозг. Я попытался указать, что ключ и значение имеют одинаковое время жизни, но это не помогло. Вот она на детской площадке . Что компилятор пытается мне сказать, и что я делаю не так? Конечно, если это может работать, когда мы заимствуем значения, оно может работать, когда мы владеем ими.

1 Ответ

2 голосов
/ 04 апреля 2020

Конечно, если это работает, когда мы заимствуем значения, оно может работать, когда мы владеем ими.

Нет. HashMap будет перемещать записи в памяти, когда ему нужно изменить размер для размещения новых записей. Если ключ заимствует значение и запись перемещается, то адрес значения изменится, и ссылка в ключе больше не будет действительной.

Для получения дополнительной информации см. Почему можно ' t Я храню значение и ссылку на это значение в одной структуре? .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...