为什么 find() 和 position() 的谓词需要不同的类型?
Why do the predicates for find() and position() require different types?
给定以下代码:
fn main() {
let vec = vec![0u8, 1, 2, 3, 4, 5, 6];
// find the first element > 3
println!("{}", vec.iter().find(|&x| *x > 3).unwrap());
// find the position of the first element > 3
println!("{}", vec.iter().position(|&x| x > 3).unwrap());
}
并查看文档:
fn find<P>(&mut self, predicate: P) -> Option<<Self as Iterator>::Item>
fn position<P>(&mut self, predicate: P) -> Option<usize>
我很难理解为什么 find()
需要 *x
而 position()
只需要 x
。两者都有 &mut self
并且在我看来好像两者都在谓词中做同样的工作。
我想这可以通过不同的 return 类型推导出来,但具体规则是什么?
我们来试试吧!
#[derive(Debug)]
struct MyNum(u8);
trait MyExt: Iterator + Sized {
fn my_find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
// Changed to take the item directly, not a reference
where
P: FnMut(Self::Item) -> bool,
{
for x in *self {
if predicate(x) {
return Some(x);
}
}
None
}
}
impl<I> MyExt for I
where
I: Iterator,
{
}
fn main() {
let mut vec = vec![0u8, 1, 2, 3, 4, 5, 6];
let vec: Vec<MyNum> = vec.drain(..).map(|x| MyNum(x)).collect();
// find the first element > 3
println!("{:?}", vec.iter().my_find(|x| x.0 > 3).unwrap());
}
编译时出现错误:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:10:18
|
10 | for x in *self {
| ^^^^^ cannot move out of borrowed content
error[E0382]: use of moved value: `x`
--> src/main.rs:12:29
|
11 | if predicate(x) {
| - value moved here
12 | return Some(x);
| ^ value used here after move
|
= note: move occurs because `x` has type `<Self as std::iter::Iterator>::Item`, which does not implement the `Copy` trait
问题是我们可以迭代不可复制的值。当我们使用 position
时,我们不需要调用谓词后的值,所以只传递值是安全的,在过程中使用它。但是,当我们调用 find
时,我们需要将值传递给谓词,然后 然后 将其作为 return 值传递。这意味着谓词不能消耗值!
给定以下代码:
fn main() {
let vec = vec![0u8, 1, 2, 3, 4, 5, 6];
// find the first element > 3
println!("{}", vec.iter().find(|&x| *x > 3).unwrap());
// find the position of the first element > 3
println!("{}", vec.iter().position(|&x| x > 3).unwrap());
}
并查看文档:
fn find<P>(&mut self, predicate: P) -> Option<<Self as Iterator>::Item>
fn position<P>(&mut self, predicate: P) -> Option<usize>
我很难理解为什么 find()
需要 *x
而 position()
只需要 x
。两者都有 &mut self
并且在我看来好像两者都在谓词中做同样的工作。
我想这可以通过不同的 return 类型推导出来,但具体规则是什么?
我们来试试吧!
#[derive(Debug)]
struct MyNum(u8);
trait MyExt: Iterator + Sized {
fn my_find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
// Changed to take the item directly, not a reference
where
P: FnMut(Self::Item) -> bool,
{
for x in *self {
if predicate(x) {
return Some(x);
}
}
None
}
}
impl<I> MyExt for I
where
I: Iterator,
{
}
fn main() {
let mut vec = vec![0u8, 1, 2, 3, 4, 5, 6];
let vec: Vec<MyNum> = vec.drain(..).map(|x| MyNum(x)).collect();
// find the first element > 3
println!("{:?}", vec.iter().my_find(|x| x.0 > 3).unwrap());
}
编译时出现错误:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:10:18
|
10 | for x in *self {
| ^^^^^ cannot move out of borrowed content
error[E0382]: use of moved value: `x`
--> src/main.rs:12:29
|
11 | if predicate(x) {
| - value moved here
12 | return Some(x);
| ^ value used here after move
|
= note: move occurs because `x` has type `<Self as std::iter::Iterator>::Item`, which does not implement the `Copy` trait
问题是我们可以迭代不可复制的值。当我们使用 position
时,我们不需要调用谓词后的值,所以只传递值是安全的,在过程中使用它。但是,当我们调用 find
时,我们需要将值传递给谓词,然后 然后 将其作为 return 值传递。这意味着谓词不能消耗值!