«неправильное количество аргументов типа» при реализации IntoIterator, который возвращает HashMap :: IntoIter - PullRequest
1 голос
/ 06 мая 2020

У меня есть следующий код:

use std::{collections::HashMap, hash::Hash, rc::Rc};

#[derive(Debug)]
pub struct LFUCache<K: Hash + Eq, V> {
    values: HashMap<Rc<K>, ValueCounter<V>>,
    capacity: usize,
    min_frequency: usize,
}

#[derive(Debug)]
struct ValueCounter<V> {
    value: V,
    count: usize,
}

impl<K: Hash + Eq, V> IntoIterator for LFUCache<K, V> {
    type Item = (Rc<K>, V);
    type IntoIter = std::collections::HashMap::IntoIter<Rc<K>, V>;

    fn into_iter(self) -> Self::IntoIter {
        return self
            .values
            .into_iter()
            .map(|(key, valueCounter)| (key, valueCounter.value));
    }
}

Выдается сообщение об ошибке:

error[E0107]: wrong number of type arguments: expected at least 2, found 0
  --> src/lib.rs:18:21
   |
18 |     type IntoIter = std::collections::HashMap::IntoIter<Rc<K>, V>;
   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected at least 2 type arguments

Я просмотрел документацию, и мой вариант использования кажется довольно аналогичным к примеру .

Как исправить?

1 Ответ

3 голосов
/ 06 мая 2020

HashMap::IntoIter, связанный тип из трейта IntoIterator, не имеет параметров типа. HashMap делает : HashMap::<Rc<K>, V>::IntoIter. Это неоднозначно, поэтому вы должны полностью определить его:

type IntoIter = <std::collections::HashMap::<Rc<K>, V> as IntoIterator>::IntoIter;

Обычно это выражается как

type IntoIter = std::collections::hash_map::IntoIter<Rc<K>, V>;

Затем вы сталкиваетесь с проблемой, которую пытаетесь решить ie. компилятор, поскольку не возвращает этот тип :

error[E0308]: mismatched types
  --> src/lib.rs:21:9
   |
21 | /         self.values
22 | |             .into_iter()
23 | |             .map(|(key, valueCounter)| (key, valueCounter.value))
   | |_________________________________________________________________^ expected struct `std::collections::hash_map::IntoIter`, found struct `std::iter::Map`
   |
   = note: expected struct `std::collections::hash_map::IntoIter<_, V>`
              found struct `std::iter::Map<std::collections::hash_map::IntoIter<_, ValueCounter<V>>, [closure@src/lib.rs:23:18: 23:65]>`

Следуя подсказкам из связанных вопросов, вы получите

use std::{collections::hash_map::IntoIter, iter::Map};

impl<K: Hash + Eq, V> IntoIterator for LFUCache<K, V> {
    type Item = (Rc<K>, V);
    type IntoIter =
        Map<IntoIter<Rc<K>, ValueCounter<V>>, fn((Rc<K>, ValueCounter<V>)) -> (Rc<K>, V)>;

    fn into_iter(self) -> Self::IntoIter {
        fn xform<K, V>((key, vc): (Rc<K>, ValueCounter<V>)) -> (Rc<K>, V) {
            (key, vc.value)
        }

        self.values.into_iter().map(xform)
    }
}

См. также :

...