【发布时间】:2021-06-01 00:39:13
【问题描述】:
假设我有以下辅助方法,它使用向量加法将两个迭代器(或IntoIterators)相加:
fn add<I1, I2, T>(a: I1, b: I2) -> impl Iterator<Item = T>
where
I1: IntoIterator<Item = T>,
I2: IntoIterator<Item = T>,
T: std::ops::Add<Output = T>,
{
a.into_iter().zip(b).map(|(x, y)| x + y)
}
可以这样使用:
fn main() {
let a = vec![1, 2, 3, 4, 5]; // Can use vectors
let b = (6..=10).map(|x| x + 1); // Or other complicated iterators
let sum_iter = add(a, b); // Can be used as an iterator if you wish to chain other functions
let sum_vec = sum_iter.collect::<Vec<i32>>(); // Or you can collect it
assert_eq!(sum_vec, vec![8, 10, 12, 14, 16]);
}
在实现这个之后,我决定我应该更改 API,以便我可以使用语法 a.add(b),这将使链接这些函数非常好。我试图实现extension trait 模式,但很快意识到这是不可能的,因为特征函数的返回类型不支持impl Trait,并且我的add 函数由于闭包@ 而无法指定具体类型987654328@ 即传入.map()
为了帮助澄清我的想法,这基本上是我尝试过的(显然这不会编译):
trait IntoIteratorMathExt
where
Self: IntoIterator,
{
fn add<I>(self, other: I) -> impl Iterator<Item = Self::Item>
where
I: IntoIterator<Item = Self::Item>,
Self::Item: std::ops::Add<Output = Self::Item>;
}
impl<T: IntoIterator> IteratorMathExt for T {
fn add<I>(self, other: I) -> impl Iterator<Item = Self::Item>
where
I: IntoIterator<Item = Self::Item>,
Self::Item: std::ops::Add<Output = Self::Item>,
{
self.into_iter().zip(other).map(|(x, y)| x + y)
}
}
fn main() {
let a = vec![1, 2, 3, 4, 5];
let b = (6..=10).map(|x| x + 1);
let sum_iter = a.add(b); // <- Really nice syntax!
let sum_vec = sum_iter.collect::<Vec<i32>>();
assert_eq!(sum_vec, vec![8, 10, 12, 14, 16]);
}
不出所料,这会产生以下编译器错误:
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> src\main.rs:34:34
|
34 | fn add<I>(self, other: I) -> impl Iterator<Item = Self::Item>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> src\main.rs:41:34
|
41 | fn add<I>(self, other: I) -> impl Iterator<Item = Self::Item>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
我理解为什么 trait 方法不支持 impl Trait,但是,我的 trait “实际上”只在一个地方实现过,所以我希望可能存在一种解决方法。
所以放弃这种方法,我想知道实现这种模式的“正确”方法是什么。
目标是能够使用迭代器 a 和 b(Iterator 或 IntoIterator,我不是 100% 什么是最好的),然后能够编写 a.add(b) 和让它返回一个Iterator,与a 和b 具有相同的关联Item 类型。
有什么建议吗?
【问题讨论】: