rust - 预期的 &-ptr,在遍历元组数组时找到元组

标签 rust

我有一个数组:

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/

相关文章:

rust - Rust 宏中相同变量的不同分隔符

rust - Rust 中的内置对象

string - 为什么 `str` 封装在 `String` 中而不是 `Box<str>` 中?

rust - 有两个结构互相引用 - Rust

rust - 如何从单独的 cargo 工作区 github 存储库中导出特征

rust - 为什么只有main.rs可以声明mod?

rust - cargo build 帮助显示所有找到的实现

rust - 宏生成代码中未使用的变量

将 `f32::MAX` 转换为 `u128` 会产生意外值

rust - 是否可以在 mio 中注册多个超时?