rust - 使用 map_keys 对扩展迭代器

标签 rust iterator

当 Rust 的 Iterator 迭代 (K, V) 对时,我尝试为它编写一些简单的扩展方法。我能想到的映射键的最简单实现涉及重用 Iterator::map像这样:

use std::iter::Map;

trait KeyedIterator<K, V>: Iterator<Item = (K, V)> {
    fn map_keys<R, F, G>(self, f: F) -> Map<Self, G>
    where
        Self: Sized,
        F: FnMut(K) -> R,
        G: FnMut((K, V)) -> (R, V),
    {
        self.map(|(key, value): (K, V)| (f(key), value))
    }
}

impl<I, K, V> KeyedIterator<K, V> for I where I: Iterator<Item = (K, V)> {}

但是,它有这个错误:

error[E0308]: mismatched types
  --> src/lib.rs:10:18
   |
10 |         self.map(|(key, value): (K, V)| (f(key), value))
   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found closure
   |
   = note: expected type `G`
              found type `[closure@src/lib.rs:10:18: 10:56 f:_]`

闭包不应该实现G吗?因为它是从(K, V)(R, V)的函数?我在这里缺少什么?

最佳答案

如果您为类型或函数声明类型参数,则该类型必须由调用者提供。但是,在您的代码中,您尝试确定类型 Gmap_keys 的体内,基于那里定义的闭包类型。

通常,让函数体确定类型的方法是使用存在返回类型(例如 Map<Self, impl FnMut((K, V)) -> (R, V)> 。但是,这在特征方法中是不允许的。

用于所有内置迭代器适配器的模式将适用于您的用例。也就是说,定义一个结构体,该结构体由您的方法返回并使其成为迭代器:

// Struct to hold the state of the iterator
struct KeyedIter<I, F> {
    iter: I,
    f: F,
}

// Make KeyedIter an iterator whenever `I` is an iterator over tuples and `F` has the 
// correct signature
impl<K, V, R, I, F> Iterator for KeyedIter<I, F>
where
    I: Iterator<Item = (K, V)>,
    F: FnMut(K) -> R,
{
    type Item = R;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(|(k, _v)| (self.f)(k))
    }
}

// A trait for adding the `map_keys` method
trait KeyedIterator<K, V> {
    fn map_keys<R, F>(self, f: F) -> KeyedIter<Self, F>
    where
        F: FnMut(K) -> R,
        Self: Sized;
}

// implement the trait for all iterators over tuples
impl<I, K, V> KeyedIterator<K, V> for I
where
    I: Iterator<Item = (K, V)>,
{
    fn map_keys<R, F>(self, f: F) -> KeyedIter<Self, F>
    where
        F: FnMut(K) -> R,
        Self: Sized,
    {
        KeyedIter { iter: self, f }
    }
}

KeyedIter struct 由调用者了解的类型参数化:前一个迭代器和映射函数。无需尝试表达中间闭包的类型 - 相反,它在迭代器的 next() 中延迟处理。方法。


另请参阅:

关于rust - 使用 map_keys 对扩展迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54289278/

相关文章:

rust - Rust 是否能够优化本地堆分配?

macros - 无法使用 rsfuzzy crate 中的宏

closures - 为什么函数参数的生存期与函数内绑定(bind)的生存期不同?

python - 如何在异常后重试迭代器 next()

c++ - 使用常量迭代器重载运算符

python - 有没有办法记住 python 迭代器中的位置?

memory-management - Rust 如何保证内存安全并防止段错误?

rust - 无法移出 `&` 指针的解除引用

c++ - 为什么迭代器使用前缀增量形式?

java - 是否有与 Python 的 'enumerate' 函数等效的 Java?