a
是类型[i32; 3]
;i32
三个s
的数组。[i32; 3]
不实现iter
方法,但确实取消引用到&[i32]
.
&[i32]
实现一个iter
产生迭代器
的方法。此迭代器实现Iterator<Item=&i32>
.
它使用&i32
而不是i32
因为迭代器必须处理任何类型的数组,并且并非所有类型都可以安全地复制。因此,它不是将自身限制为可复制类型,而是通过引用而不是值来迭代元素。
find
是为所有Iterator
s 定义的方法。它使您可以查看每个元素并返回与谓词匹配的元素。问题:如果迭代器产生不可复制的值,那么将值传递给谓词将无法从find
. 该值无法重新生成,因为迭代器(通常)不可重绕或可重新启动。因此,find
必须通过引用而不是按值将元素传递给谓词。
因此,如果您有一个实现 的迭代器Iterator<Item=T>
,则Iterator::find
需要一个接受 a&T
并返回 a的谓词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()
是over的迭代器&i32
,而不是.的迭代器i32
。如果您查看 的文档Iterator::find
,您会看到 for Iterator<Item=T>
,它返回一个Option<T>
. 因此,在这种情况下,它返回一个Option<&i32>
,所以这就是你需要比较它的。
[1]:只有在谈论非Copy
类型时,差异才有意义。例如,|&&x| ..
不能在 a 上工作&&String
,因为您必须能够String
从引用后面移出,这是不允许的。但是,|x| **x ..
会起作用,因为这只是在不移动任何东西的情况下到达参考内部。