为什么在闭包参数中使用“&&”?
Why is "&&" being used in closure arguments?
我有两个关于 this example 的问题:
let a = [1, 2, 3];
assert_eq!(a.iter().find(|&&x| x == 2), Some(&2));
assert_eq!(a.iter().find(|&&x| x == 5), None);
为什么在闭包参数中使用 &&x
而不是 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)
?
1) 我觉得这本书解释的很好,也许我下面的 .cloned()
的例子会有用。但是由于 .iter()
遍历引用,您必须另外指定引用,因为 find
需要引用。
2) .iter()
正在遍历引用;因此,你找到一个参考。
您可以使用 .cloned()
来查看如果您不必处理引用会是什么样子:
assert_eq!(a.iter().cloned().find(|&x| x == 2), Some(2));
a
是 [i32; 3]
类型;三个 i32
的数组。
[i32; 3]
没有实现 iter
方法,但它 确实 取消对 &[i32]
的引用。
&[i32]
implements an iter
method 产生一个迭代器。
This iterator 实施 Iterator<Item=&i32>
.
它使用 &i32
而不是 i32
因为迭代器必须在 any 类型的数组上工作,并且并非所有类型都可以安全地复制。因此,它不是将自己限制为可复制的类型,而是通过引用而不是值来迭代元素。
find
is a method 为所有 Iterator
定义。它使您可以查看每个元素和 return 与谓词匹配的元素。问题:如果迭代器产生不可复制的值,那么将值传递给谓词将无法从 find
中 return 它。该值无法重新生成,因为迭代器(通常)不可倒带或可重启。因此,find
必须按引用而不是按值将元素传递给谓词。
因此,如果您有一个实现 Iterator<Item=T>
的迭代器,那么 Iterator::find
需要一个带有 &T
和 return 的谓词 bool
。 [i32]::iter
生成一个实现 Iterator<Item=&i32>
的迭代器。因此,调用数组迭代器的 Iterator::find
需要一个带有 &&i32
的谓词。也就是说,它将谓词传递给指向相关元素的指针。
所以如果你写 a.iter().find(|x| ..)
,x
的类型就是 &&i32
。这不能直接与文字 i32
值 2
进行比较。有几种方法可以解决这个问题。一种是显式取消引用 x
: a.iter().find(|x| **x == 2)
。另一种是使用模式匹配来解构双重引用:a.iter().find(|&&x| x == 2)
。在这种情况下,这两种方法 完全 做同样的事情。 [1]
至于为什么用Some(&2)
:因为a.iter()
是&i32
的迭代器,不是[=12=的迭代器].如果您查看 Iterator::find
的文档,您会看到 Iterator<Item=T>
的 return 是 Option<T>
。因此,在这种情况下,它 return 是一个 Option<&i32>
,因此您需要将其与之进行比较。
[1]:仅当您谈论非 Copy
类型时,差异才重要。例如,|&&x| ..
不适用于 &&String
,因为您必须能够将 String
从引用后面移出,而这是不允许的。然而,|x| **x ..
会 工作,因为那只是在不移动任何东西的情况下到达参考内部。
我有两个关于 this example 的问题:
let a = [1, 2, 3];
assert_eq!(a.iter().find(|&&x| x == 2), Some(&2));
assert_eq!(a.iter().find(|&&x| x == 5), None);
为什么在闭包参数中使用
&&x
而不是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)
?
1) 我觉得这本书解释的很好,也许我下面的 .cloned()
的例子会有用。但是由于 .iter()
遍历引用,您必须另外指定引用,因为 find
需要引用。
2) .iter()
正在遍历引用;因此,你找到一个参考。
您可以使用 .cloned()
来查看如果您不必处理引用会是什么样子:
assert_eq!(a.iter().cloned().find(|&x| x == 2), Some(2));
a
是 [i32; 3]
类型;三个 i32
的数组。
[i32; 3]
没有实现 iter
方法,但它 确实 取消对 &[i32]
的引用。
&[i32]
implements an iter
method 产生一个迭代器。
This iterator 实施 Iterator<Item=&i32>
.
它使用 &i32
而不是 i32
因为迭代器必须在 any 类型的数组上工作,并且并非所有类型都可以安全地复制。因此,它不是将自己限制为可复制的类型,而是通过引用而不是值来迭代元素。
find
is a method 为所有 Iterator
定义。它使您可以查看每个元素和 return 与谓词匹配的元素。问题:如果迭代器产生不可复制的值,那么将值传递给谓词将无法从 find
中 return 它。该值无法重新生成,因为迭代器(通常)不可倒带或可重启。因此,find
必须按引用而不是按值将元素传递给谓词。
因此,如果您有一个实现 Iterator<Item=T>
的迭代器,那么 Iterator::find
需要一个带有 &T
和 return 的谓词 bool
。 [i32]::iter
生成一个实现 Iterator<Item=&i32>
的迭代器。因此,调用数组迭代器的 Iterator::find
需要一个带有 &&i32
的谓词。也就是说,它将谓词传递给指向相关元素的指针。
所以如果你写 a.iter().find(|x| ..)
,x
的类型就是 &&i32
。这不能直接与文字 i32
值 2
进行比较。有几种方法可以解决这个问题。一种是显式取消引用 x
: a.iter().find(|x| **x == 2)
。另一种是使用模式匹配来解构双重引用:a.iter().find(|&&x| x == 2)
。在这种情况下,这两种方法 完全 做同样的事情。 [1]
至于为什么用Some(&2)
:因为a.iter()
是&i32
的迭代器,不是[=12=的迭代器].如果您查看 Iterator::find
的文档,您会看到 Iterator<Item=T>
的 return 是 Option<T>
。因此,在这种情况下,它 return 是一个 Option<&i32>
,因此您需要将其与之进行比较。
[1]:仅当您谈论非 Copy
类型时,差异才重要。例如,|&&x| ..
不适用于 &&String
,因为您必须能够将 String
从引用后面移出,而这是不允许的。然而,|x| **x ..
会 工作,因为那只是在不移动任何东西的情况下到达参考内部。