我有一个数组:
const adjacent: [(i8, i8); 8] =
[(-1, -1), (-1, 0), (-1, 1), (-1, 0), (1, 0), (1, 1), (1, 0), (1, -1)];
此数组表示 ROWxCOLUMN 网格中单元格的所有相邻邻居。要遍历此数组以找到所有邻居,我会这样做
for k in adjacent.into_iter() {
let (i, c) = (k.0, k.1);
if let Some(a) = grid.get(r+i, j+c) {
/* ... */
}
}
第二行似乎可以用 K 代替,但是如果你写 for (i, c) in adjacency.into_iter() { ...
error: type mismatch resolving `<core::slice::Iterator>::Item == (_, _)`:
expected &-ptr
found tuple
这是怎么回事?有人可以解释为什么我不能这样做吗?
最佳答案
解决方案
那里发生了很多事情。首先是工作代码:
for &(i, c) in &adjacent { }
下面是更详细的解释。
问题
您的迭代器吐出类型为 &(i8, i8)
的项目这是对实际数据的引用。你试图用 (i, c)
来解构它图案。这是行不通的,因为它们是两种不同的类型;即对元组和元组的引用。因此,如果您添加 &
对于您的模式,模式的类型和项目匹配,编译器可以愉快地为您解构它。
下次如何自己解决
完整的错误信息是:
<anon>:11:5: 11:42 error: type mismatch resolving `<core::slice::Iter<'_, (i8, i8)> as core::iter::Iterator>::Item == (_, _)`:
expected &-ptr,
found tuple [E0271]
<anon>:11 for (i, c) in adjacent.into_iter() {}
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
这个错误消息实际上可以改进,但是:让我们深入研究一下。编译器表示它无法将实际类型(在左侧,core::slice::Iter<'_, (i8, i8)>
)解析为另一种类型,该类型以某种方式“请求”(在右侧,<core::iter::Iterator>::Item == (_, _)
)。
您“请求”了一个项目类型为 (_, _)
的迭代器,这是有道理的,因为这正是你写的:(i, c)
.那么左边的类型呢?如果我们查一下in the documentation我们可以看到它实现了 Iterator
type Item = &'a T
的特征.我们可以忽略显式生命周期 'a
只需注意它是对类型参数 T
的引用.但我们知道什么T
通过查看错误消息:core::slice::Iter<'_, (i8, i8)>
.所以T
是(i8, i8)
因此迭代器的项类型是 &(i8, i8)
.
关于IntoIterator
和for循环
您使用了明确的 .into_iterator()
调用数组。你这样做的原因是可以理解的:for _ in adjacent
失败并显示消息
the trait `core::iter::Iterator` is not implemented for the type `[(i8, i8); 8]`
这很令人困惑:为什么不能迭代大小为 8 的数组?事实上,要理解它,你必须知道如何for
循环工作。
您要迭代的“事物”必须实现 Iterator
直接或 IntoIterator
.大多数数据结构(数组,Vec
,...)不实现 Iterator
直接,但是 IntoIterator
. array
原语确实实现了 IntoIterator
,也是——有点。如果我们看一下the documentation ,我们可以看到IntoIterator
有两种实现方式对于每个数组长度:
impl<'a, T> IntoIterator for &'a [T; 8]
type Item = &'a T
impl<'a, T> IntoIterator for &'a mut [T; 8]
type Item = &'a mut T
注意这个特性不是直接为数组类型实现的,而是为它的引用实现的。这些实现也有一个引用作为 Item
类型。那么为什么不是 IntoIterator
已实现 for [T; 8]
直接地? 因为我们不能移出一个数组。
为了解决这个问题,我们写了&adjacent
而不是 adjacent
-- 对数组的引用。然后编译器会找到正确的实现。为什么手册 into_iterator
打电话工作?好吧……那是一个完全不同的故事,但简而言之:.
方法调用自行在值类型和引用类型之间进行转换。
TL;DR:所以如果你有一个数据结构 adjacent
某种类型(数组,Vec
,...),你基本上有三种可能性:
-
for _ in &adjacent
:您想迭代对项目的不可变引用。大多数时候这是您想要的! -
for _ in &mut adjacent
: 您想要迭代可变引用以修改项目。 -
for _ in adjacent
:您想获得项目的所有权,从而使数据结构之后无法使用。最不常见的选择!甚至不适用于某些数据结构。
关于rust - 预期的 &-ptr,在遍历元组数组时找到元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33836892/