为什么迭代器筛选器中对泛型类型的比较操作不起作用?



我试图理解为什么以下代码无法编译(Playground(:

fn inspection<I>(iter: I)
where 
I: Iterator, 
I::Item: Ord,
{
let inspection = iter
.filter(|x| x > 0);
}
fn main() {
let data = vec![1, 2, 3];
inspection(data.iter()); // or inspection(data.into_iter());
}

错误是:

error[E0308]: mismatched types
--> src/main.rs:9:25
|
9 |         .filter(|x| x > 0);
|                         ^ expected reference, found integral variable
|
= note: expected type `&<I as std::iter::Iterator>::Item`
found type `{integer}`

我试图遵循此处解释的各种替代方案(通过取消引用元素(,但没有成功。

第一次尝试:

.filter(|x| **x > 0); 
error[E0614]: type `<I as std::iter::Iterator>::Item` cannot be dereferenced
--> src/main.rs:13:21
|
13 |         .filter(|x| **x > 0);
|  

第二次尝试:

.filter(|&x| *x > 0);
error[E0614]: type `<I as std::iter::Iterator>::Item` cannot be dereferenced
--> src/main.rs:13:22
|
13 |         .filter(|&x| *x > 0);
|    

为什么程序不编译?

最大的问题(Lukas 涵盖了另一个问题(是您将迭代器的泛型项与整数进行比较,而PartialOrd/Ord提供的比较仅在相同类型之间工作:

pub trait Ord: Eq + PartialOrd<Self> {
fn cmp(&self, other: &Self) -> Ordering;
...
}

为了使类型T与数字(在本例中为0(相当,T必须是数字,0也需要是T类型。包含有用数字特征的num箱可以帮助这里提供通用0Zero特征:

extern crate num;
use num::Zero;
fn inspection<'a, I, T: 'a>(iter: I)
where
I: Iterator<Item = &'a T>,
T: Zero + PartialOrd // T is an ordered number
{
let inspection = iter.filter(|&x| *x > T::zero()); // T::zero() is 0 of the same type as T
}
fn main() {
let data = vec![1, 2, 3];
inspection(data.iter());
}

你真的快要解决第一个问题了!您尝试过:

  • filter(|x| x > 0)
  • filter(|x| **x > 0)
  • filter(|&x| *x > 0)

解决方案是:filter(|x| *x > 0)filter(|&x| x > 0).

要了解原因,让我们再次仔细查看错误消息:

9 |         .filter(|x| x > 0);
|                         ^ expected reference, found integral variable
|
= note: expected type `&<I as std::iter::Iterator>::Item`
found type `{integer}`

它说它期望类型&<I as std::iter::Iterator>::Item并得到类型{integer}。这意味着差异是一个参考。您无法将&i32i32进行比较。因此,您可以使用*(取消引用运算符(或|&x|模式(也取消引用值(删除一个&。但是如果你将两者结合起来,这会产生与**相同的效果:它试图取消引用两次。这是不可能的,因为该类型只包含一个引用。


但是,由于更复杂的问题,它仍然无法编译。您可以在此处阅读有关它的更多信息:

  • Rust 中数字函数的特征

最新更新