Rust: как объединить API ввода с собственными данными?

#rust #hashmap #ownership

#Ржавчина #hashmap #владение

Вопрос:

У меня есть HashMap и я хотел бы обновить значение, если оно существует, и в противном случае добавить значение по умолчанию. Обычно я бы сделал это так:

 some_map.entry(some_key)
    .and_modify(|e| modify(e))
    .or_insert(default)
  

Но теперь у меня modify есть тип fn(T)->T , но проверка заимствования, очевидно, не позволит мне писать:

 some_map.entry(some_key)
    .and_modify(|e| *e = modify(*e))
    .or_insert(default)
  

Какой предпочтительный способ сделать это в Rust? Должен ли я просто использовать remove and insert ?

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

1. Я думаю, что в таком контексте, например HashMap.entry(some_key).and_modify(f) , вам следует сначала рассмотреть вопрос о предоставлении f типа fn(amp;mut T) . fn(T)->T это просто неправильный выбор.

Ответ №1:

Предполагая, что вы можете создать пустую версию своего T по дешевке, вы могли бы использовать mem::replace :

 some_map.entry(some_key)
    .and_modify(|e| {
        // swaps the second parameter in and returns the value which was there
        let mut v = mem::replace(e, T::empty());
        v = modify(v);
        // puts the value back in and discards the empty one
        mem::replace(e, v);
    })
    .or_insert(default)
  

это предполагает modify , что вы не паникуете, в противном случае вы обнаружите, что «пустое» значение остается на вашей карте. Но у вас была бы аналогичная проблема с remove / insert .

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

1. Если пустой T не так просто, но вы управляете картой, переключение на a HashMap<K, Option<T>> может помочь.

2. Существует также этот replace_with ящик, если вы можете пойти на компромисс.