我正在尝试为Iterator实现mean
方法,就像使用sum
一样。
但是,sum
是Iterator
方法,因此我决定为实现Iterator
的任何类型实现特征:
pub trait Mean<A = Self>: Sized {
fn mean<I: Iterator<Item = A>>(iter: I) -> f64;
}
impl Mean for u64 {
fn mean<I: Iterator<Item = u64>>(iter: I) -> f64 {
//use zip to start enumeration from 1, not 0
iter.zip((1..))
.fold(0., |s, (e, i)| (e as f64 + s * (i - 1) as f64) / i as f64)
}
}
impl<'a> Mean<&'a u64> for u64 {
fn mean<I: Iterator<Item = &'a u64>>(iter: I) -> f64 {
iter.zip((1..))
.fold(0., |s, (&e, i)| (e as f64 + s * (i - 1) as f64) / i as f64)
}
}
trait MeanIterator: Iterator {
fn mean(self) -> f64;
}
impl<T: Iterator> MeanIterator for T {
fn mean(self) -> f64 {
Mean::mean(self)
}
}
fn main() {
assert_eq!([1, 2, 3, 4, 5].iter().mean(), 3.);
}
错误:
error[E0282]: type annotations needed
--> src/main.rs:26:9
|
26 | Mean::mean(self)
| ^^^^^^^^^^ cannot infer type for `Self`
有没有办法修复代码,或者在Rust中是不可能的?
答案 0 :(得分:5)
就像使用
一样sum
让我们来看看sum
的工作原理:
fn sum<S>(self) -> S
where Self: Sized,
S: Sum<Self::Item>,
sum
在任何迭代器上实现,只要结果类型S
为迭代值实现Sum
即可。 调用者可以选择结果类型。 Sum
定义为:
pub trait Sum<A = Self> {
fn sum<I>(iter: I) -> Self
where I: Iterator<Item = A>;
}
Sum::sum
采用A
的迭代器,并生成一个从中实现的类型的值。
我们只需复制粘贴结构,更改Sum
Mean
并简单实现:
trait MeanExt: Iterator {
fn mean<M>(self) -> M
where M: Mean<Self::Item>,
Self: Sized,
{
M::mean(self)
}
}
impl<I: Iterator> MeanExt for I {}
trait Mean<A = Self> {
fn mean<I>(iter: I) -> Self
where I: Iterator<Item = A>;
}
impl Mean for f64 {
fn mean<I>(iter: I) -> Self
where I: Iterator<Item = f64>
{
let mut sum = 0.0;
let mut count: usize = 0;
for v in iter {
sum += v;
count += 1;
}
if count > 0 {
sum / (count as f64)
} else {
0.0
}
}
}
impl<'a> Mean<&'a f64> for f64 {
fn mean<I>(iter: I) -> Self
where I: Iterator<Item = &'a f64>
{
iter.cloned().mean()
}
}
fn main() {
let mean: f64 = [1.0, 2.0, 3.0].iter().mean();
println!("{:?}", mean);
let mean: f64 = vec![-1.0, 2.0, 1.0].into_iter().mean();
println!("{:?}", mean);
}
答案 1 :(得分:2)
你可以这样做,例如:
pub trait Mean {
fn mean(self) -> f64;
}
impl<F, T> Mean for T
where T: Iterator<Item = F>,
F: std::borrow::Borrow<f64>
{
fn mean(self) -> f64 {
self.zip((1..))
.fold(0.,
|s, (e, i)| (*e.borrow() + s * (i - 1) as f64) / i as f64)
}
}
fn main() {
assert_eq!([1f64, 2f64, 3f64, 4f64, 5f64].iter().mean(), 3.);
assert_eq!(vec![1f64, 2f64, 3f64, 4f64, 5f64].iter().mean(), 3.);
assert_eq!(vec![1f64, 2f64, 3f64, 4f64, 5f64].into_iter().mean(), 3.);
}
我使用Borrow
特征来支持f64
和&f64
上的迭代器。