【发布时间】:2021-11-15 07:28:43
【问题描述】:
我决定尝试使用一揽子实现在 Rust 中创建一个 trait,而要实现的测试方法是一个 trait,它通过迭代器连同元素一起返回 argmax。现在的实现是
use num::Bounded;
trait Argmax<T> {
fn argmax(self) -> (usize, T);
}
impl<I, T> Argmax<T> for I
where
I: Iterator<Item = T>,
T: std::cmp::PartialOrd + Bounded,
{
fn argmax(self) -> (usize, T) {
self.enumerate()
.fold((0, T::min_value()), |(i_max, val_max), (i, val)| {
if val >= val_max {
(i, val)
} else {
(i_max, val_max)
}
})
}
}
用这段代码测试它
fn main() {
let v = vec![1., 2., 3., 4., 2., 3.];
println!("v: {:?}", v);
let (i_max, v_max) = v.iter().copied().argmax();
println!("i_max: {}\nv_max: {}", i_max, v_max);
}
工作,而
fn main() {
let v = vec![1., 2., 3., 4., 2., 3.];
println!("v: {:?}", v);
let (i_max, v_max) = v.iter().argmax();
println!("i_max: {}\nv_max: {}", i_max, v_max);
}
无法编译,并给出以下错误:
--> src/main.rs:27:35
|
27 | let (i_max, v_max) = v.iter().argmax();
| ^^^^^^ method cannot be called on `std::slice::Iter<'_, {float}>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`<&std::slice::Iter<'_, {float}> as Iterator>::Item = _`
which is required by `&std::slice::Iter<'_, {float}>: Argmax<_>`
`&std::slice::Iter<'_, {float}>: Iterator`
which is required by `&std::slice::Iter<'_, {float}>: Argmax<_>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0599`.
我认为问题源于.iter() 循环引用,而.iter().copied() 循环实际值,但我仍然无法理解错误消息以及如何使其通用和工作循环引用。
编辑:在被建议尝试使用关联类型而不是泛型类型来实现上述内容后,最终得到了这个工作实现以供以后参考:
trait Argmax {
type Maximum;
fn argmax(self) -> Option<(usize, Self::Maximum)>;
}
impl<I> Argmax for I
where
I: Iterator,
I::Item: std::cmp::PartialOrd,
{
type Maximum = I::Item;
fn argmax(mut self) -> Option<(usize, Self::Maximum)> {
let v0 = match self.next() {
Some(v) => v,
None => return None,
};
Some(
self.enumerate()
.fold((0, v0), |(i_max, val_max), (i, val)| {
if val > val_max {
(i + 1, val) // Add 1 as index is one off due to next() above
} else {
(i_max, val_max)
}
}),
)
}
}
此实现还删除了 Bounded 作为依赖项,而是检查迭代器是否为空,如果不是,则使用迭代器返回的第一个元素初始化当前最大值。此实现返回它找到的第一个最大值的索引。
【问题讨论】: