我有一个数组:
const adjacent: [(i8, i8); 8] =
[(-1, -1), (-1, 0), (-1, 1), (-1, 0), (1, 0), (1, 1), (1, 0), (1, -1)];
Run Code Online (Sandbox Code Playgroud)
此数组表示ROW x COLUMN网格中单元格的所有相邻邻居.为了遍历这个数组以找到所有邻居,我做到了
for k in adjacent.into_iter() {
let (i, c) = (k.0, k.1);
if let Some(a) = grid.get(r+i, j+c) {
/* ... */
}
}
Run Code Online (Sandbox Code Playgroud)
第二行似乎可以替代K,但如果你写,这会导致错误 for (i, c) in adjacency.into_iter() { ...
error: type mismatch resolving `<core::slice::Iterator>::Item == (_, _)`:
expected &-ptr
found tuple
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?有人可以解释为什么我不能这样做吗?
那里发生了很多事情.首先是工作代码:
for &(i, c) in &adjacent { }
Run Code Online (Sandbox Code Playgroud)
更详细的解释如下.
您的迭代器正在吐出类型的项目,这些项目&(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() {}
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
这个错误信息实际上可以改进,但尽管如此:让我们深入研究它.编译器说它无法解析实际类型(在左侧core::slice::Iter<'_, (i8, i8)>)作为另一种类型,以某种方式"请求"(在右侧<core::iter::Iterator>::Item == (_, _)).
你"请求"了一个具有项目类型的迭代器(_, _),这是有道理的,因为这正是你写的:(i, c).那左边的类型怎么样?如果我们在文档中查找它,我们可以看到它实现了Iterator特性type Item = &'a T.我们可以忽略显式生存期'a,只需注意它是对type参数的引用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]`
Run Code Online (Sandbox Code Playgroud)
这很令人困惑:为什么你不能迭代8号大小的数组?的确,要理解它,你必须知道for循环是如何工作的.
你要迭代的"东西"必须Iterator直接实现或IntoIterator.大多数数据结构(数组,Vec......)不Iterator直接实现,但是IntoIterator.该array原始确实实现了IntoIterator,太-有点.如果我们看一下文档,我们可以看到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
Run Code Online (Sandbox Code Playgroud)
注意这个特性是如何直接为数组类型实现的,而是为了对它的引用.这些实现也有一个引用作为Item类型.那为什么不直接IntoIterator实施for [T; 8]呢?因为我们无法移出阵列.
为了解决这个问题,我们编写&adjacent而不是adjacent- 对数组的引用.然后编译器将找到正确的实现.为什么手动into_iterator调用有效?嗯......这是一个完全不同的故事,但简而言之:.方法调用在它自己的值和引用类型之间进行转换.
TL; DR:所以如果你有adjacent某种类型的数据结构(数组Vec,......),你基本上有三种可能:
for _ in &adjacent:您想要对项目的不可变引用进行迭代.这是你大多数时候想要的!for _ in &mut adjacent:您希望迭代可变引用以修改项目.for _ in adjacent:您希望获取项目的所有权,从而使数据结构在之后无法使用.最不常见的选择!甚至不适用于某些数据结构.| 归档时间: |
|
| 查看次数: |
1452 次 |
| 最近记录: |