为什么是“&"?在闭包参数中使用? [英] Why is "&&" being used in closure arguments?

查看:14
本文介绍了为什么是“&"?在闭包参数中使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于这个例子,我有两个问题:

let a = [1, 2, 3];

assert_eq!(a.iter().find(|&&x| x == 2), Some(&2));
assert_eq!(a.iter().find(|&&x| x == 5), None);

  1. 为什么在闭包参数中使用 &&x 而不是 x?我知道 & 正在传递对对象的引用,但是使用它两次意味着什么?

  1. Why is &&x used in the closure arguments rather than just x? I understand that & is passing a reference to an object, but what does using it twice mean?

我不明白文档说的是什么:

I don't understand what the documentation says:

因为 find() 接受一个引用,并且许多迭代器对引用进行迭代,所以这可能会导致参数是双重引用的混淆情况.您可以在下面的示例中看到这种效果,使用 &&x.

Because find() takes a reference, and many iterators iterate over references, this leads to a possibly confusing situation where the argument is a double reference. You can see this effect in the examples below, with &&x.

  • 为什么使用 Some(&2) 而不是 Some(2)?

    推荐答案

    a is of type [i32;3];三个 i32 的数组.<代码>[i32;3] 没有实现 iter 方法,但它确实取消了对 &[i32] 的引用.&[i32] 实现了一个 iter 方法 产生一个迭代器.这个迭代器实现了Iterator;.

    a is of type [i32; 3]; an array of three i32s. [i32; 3] does not implement an iter method, but it does dereference into &[i32]. &[i32] implements an iter method which produces an iterator. This iterator implements Iterator<Item=&i32>.

    它使用 &i32 而不是 i32 因为迭代器必须处理 any 类型的数组,而不是所有类型都可以安全复制.因此,它不是将自身限制为可复制类型,而是通过引用而不是通过值迭代元素.

    It uses &i32 rather than i32 because the iterator has to work on arrays of any type, and not all types can be safely copied. So rather than restrict itself to copyable types, it iterates over the elements by reference rather than by value.

    find 是一个为所有 Iterator 定义的方法.它让您查看每个元素并返回与谓词匹配的元素.问题:如果迭代器产生不可复制的值,那么将值传递给谓词将使其无法从 find 返回.该值无法重新生成,因为迭代器(通常)不可重绕或重新启动.因此,find 必须通过引用而不是通过值将元素传递给谓词.

    find is a method defined for all Iterators. It lets you look at each element and return the one that matches the predicate. Problem: if the iterator produces non-copyable values, then passing the value into the predicate would make it impossible to return it from find. The value cannot be re-generated, since iterators are not (in general) rewindable or restartable. Thus, find has to pass the element to the predicate by-reference rather than by-value.

    因此,如果您有一个实现 Iterator 的迭代器,那么 Iterator::find 需要一个带有 &T 的谓词 并返回一个 bool.[i32]::iter 生成一个实现 Iterator 的迭代器.因此,对数组迭代器调用的 Iterator::find 需要一个带有 &&i32 的谓词.也就是说,它向谓词传递一个指向所讨论元素的指针的指针.

    So, if you have an iterator that implements Iterator<Item=T>, then Iterator::find requires a predicate that takes a &T and returns a bool. [i32]::iter produces an iterator that implements Iterator<Item=&i32>. Thus, Iterator::find called on an array iterator requires a predicate that takes a &&i32. That is, it passes the predicate a pointer to a pointer to the element in question.

    因此,如果您要编写 a.iter().find(|x| ..)x 的类型将是 &&i32.这不能直接与文字 i322 进行比较.有几种方法可以解决这个问题.一种是显式取消引用 x:a.iter().find(|x| **x == 2).另一种是使用模式匹配来解构双重引用:a.iter().find(|&&x| x == 2).在这种情况下,这两种方法完全做同样的事情.[1]

    So if you were to write a.iter().find(|x| ..), the type of x would be &&i32. This cannot be directly compared to the literal i32 value 2. There are several ways of fixing this. One is to explicitly dereference x: a.iter().find(|x| **x == 2). The other is to use pattern matching to destructure the double reference: a.iter().find(|&&x| x == 2). These two approaches are, in this case, doing exactly the same thing. [1]

    至于为什么使用Some(&2):因为a.iter()&i32的迭代器,不是 i32 的迭代器.如果您查看 Iterator::find 的文档,您会看到对于 Iterator,它返回一个 Option.因此,在这种情况下,它返回一个 Option<&i32>,因此您需要与它进行比较.

    As for why Some(&2) is used: because a.iter() is an iterator over &i32, not an iterator of i32. If you look at the documentation for Iterator::find, you'll see that for Iterator<Item=T>, it returns an Option<T>. Hence, in this case, it returns an Option<&i32>, so that's what you need to compare it against.

    [1]:只有在讨论非Copy 类型时,差异才重要.例如,|&&x|.. 不适用于 &&String,因为您必须能够将 String 从引用后面移出,这是不允许的.但是,<代码>|x|**x .. 工作,因为那只是到达引用内部而不移动任何东西.

    [1]: The differences only matter when you're talking about non-Copy types. For example, |&&x| .. wouldn't work on a &&String, because you'd have to be able to move the String out from behind the reference, and that's not allowed. However, |x| **x .. would work, because that is just reaching inside the reference without moving anything.

    这篇关于为什么是“&amp;"?在闭包参数中使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆