为什么find()和position()的谓词需要不同的类型?

Ode*_*Wat 3 rust

给出以下代码:

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());
}
Run Code Online (Sandbox Code Playgroud)

并查看文档:

fn find<P>(&mut self, predicate: P) -> Option<<Self as Iterator>::Item>

fn position<P>(&mut self, predicate: P) -> Option<usize>
Run Code Online (Sandbox Code Playgroud)

我发现很难理解为什么find()需要*xposition()需要x.两者都有&mut self,它看起来好像在谓词中都做同样的工作.

我想这可以通过不同的返回类型推断出来,但具体的规则是什么?

She*_*ter 5

我们来试试吧!

#[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());
}
Run Code Online (Sandbox Code Playgroud)

这会编译错误:

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
Run Code Online (Sandbox Code Playgroud)

问题是我们可以迭代不可复制的值.当我们使用时position,在调用谓词之后我们不需要该值,因此只传入值,并在此过程中使用它是安全的.find但是,当我们调用时,我们需要将值传递给谓词,然后将其作为返回值传递.这意味着谓词不能消耗该值!

  • 这解释了原因。我不满意。但我想那不是你的错。 (2认同)
  • 对于它的价值,我很高兴 Rust 确保我在移动后不会使用 use 值!^_^ 我可以看到两种解决方案来统一问题:两者都可以引用,或者可能有一个具有额外的“T: Copy”绑定的“find_copyable”。对我来说两者都不是很好。 (2认同)