当 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)
的函数?我在这里缺少什么?
最佳答案
如果您为类型或函数声明类型参数,则该类型必须由调用者提供。但是,在您的代码中,您尝试确定类型 G
在 map_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/