我试图理解为什么以下代码无法编译(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
箱可以帮助这里提供通用0
的Zero
特征:
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}
。这意味着差异是一个参考。您无法将&i32
与i32
进行比较。因此,您可以使用*
(取消引用运算符(或|&x|
模式(也取消引用值(删除一个&
。但是如果你将两者结合起来,这会产生与**
相同的效果:它试图取消引用两次。这是不可能的,因为该类型只包含一个引用。
但是,由于更复杂的问题,它仍然无法编译。您可以在此处阅读有关它的更多信息:
- Rust 中数字函数的特征