如何分配给匹配分支内的匹配表达式中使用的变量?

2023-12-05

我正在尝试实现一个通用功能join()它可以在任何迭代器的迭代器上工作。我的借用检查器有问题match里面的表达式next()方法实施。这是我的代码的简化版本:

pub struct Join<I>
where
    I: Iterator,
    I::Item: IntoIterator,
{
    outer_iter: I,
    inner_iter: Option<<I::Item as IntoIterator>::IntoIter>,
}

impl<I> Join<I>
where
    I: Iterator,
    I::Item: IntoIterator,
{
    pub fn new(mut iter: I) -> Join<I> {
        let inner_iter = iter.next().map(|it| it.into_iter());
        Join {
            outer_iter: iter,
            inner_iter,
        }
    }
}

impl<I> Iterator for Join<I>
where
    I: Iterator,
    I::Item: IntoIterator,
{
    type Item = <I::Item as IntoIterator>::Item;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            match &mut self.inner_iter {
                Some(ref mut it) => match it.next() {
                    Some(x) => {
                        return Some(x);
                    }
                    None => {
                        self.inner_iter = self.outer_iter.next().map(|it| it.into_iter());
                    }
                },
                None => {
                    return None;
                }
            }
        }
    }
}

pub trait MyItertools: Iterator {
    fn join(self) -> Join<Self>
    where
        Self: Sized,
        Self::Item: IntoIterator,
    {
        Join::new(self)
    }
}

impl<I> MyItertools for I where I: Iterator {}

#[cfg(test)]
mod test {
    use super::MyItertools;

    #[test]
    fn it_works() {
        let input = [[1], [2]];
        let expected = [&1, &2];
        assert_eq!(input.iter().join().collect::<Vec<_>>(), expected);
    }
}

错误文本:

error[E0506]: cannot assign to `self.inner_iter` because it is borrowed
  --> src/main.rs:39:25
   |
33 |             match &mut self.inner_iter {
   |                        --------------- borrow of `self.inner_iter` occurs here
...
39 |                         self.inner_iter = self.outer_iter.next().map(|it| it.into_iter());
   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `self.inner_iter` occurs here

我理解为什么借用检查器抱怨我的代码,但我没有找到一个好的解决方案,只有一个丑陋的解决方法:

fn next(&mut self) -> Option<Self::Item> {
    loop {
        match self.inner_iter.take() {
            Some(mut it) => {
                match it.next() {
                    Some(x) => { self.inner_iter = Some(it); return Some(x); }
                    None => { self.inner_iter = self.outer_iter.next().map(|it| it.into_iter()); }
                }
            }
            None => { return None; }
        }
    }
}

我想这样的情况经常发生;我怎样才能重写我的代码来处理它们或避免它们?


这是问题的更简单的再现:

fn main() {
    let mut a = (42, true);
    match a {
        (ref _i, true) => a = (99, false),
        (ref _i, false) => a = (42, true),
    }
    println!("{:?}", a);
}
error[E0506]: cannot assign to `a` because it is borrowed
 --> src/main.rs:4:27
  |
4 |         (ref _i, true) => a = (99, false),
  |          ------           ^^^^^^^^^^^^^^^ assignment to borrowed `a` occurs here
  |          |
  |          borrow of `a` occurs here

error[E0506]: cannot assign to `a` because it is borrowed
 --> src/main.rs:5:28
  |
5 |         (ref _i, false) => a = (42, true),
  |          ------            ^^^^^^^^^^^^^^ assignment to borrowed `a` occurs here
  |          |
  |          borrow of `a` occurs here

这是基于 AST 的借用检查器的弱点。什么时候非词汇生命周期已启用,这按原样工作。增强的基于 MIR 的借用检查器可以看到在您尝试替换匹配变量时没有借用它。


对于它的价值,你的join只是一个flat_map:

input.iter().flat_map(|x| x)

Or a flatten:

input.iter().flatten()

你可以看到这些如何实施next另一个想法:

fn next(&mut self) -> Option<Self::Item> {
    loop {
        if let Some(v) = self.inner_iter.as_mut().and_then(|i| i.next()) {
            return Some(v);
        }
        match self.outer_iter.next() {
            Some(x) => self.inner_iter = Some(x.into_iter()),
            None => return None,
        }
    }
}

这清楚地表明迭代器值不really从...借inner_iter.


不看的情况下flatten,我会选择明确表明不存在重叠借用taking the Option并恢复它(如果是)Some,正如您所做的那样:

match self.inner_iter.take() {
    Some(mut it) => match it.next() {
        Some(x) => {
            self.inner_iter = Some(it);
            return Some(x);
        }
        None => {
            self.inner_iter = self.outer_iter.next().map(|it| it.into_iter());
        }
    },
    None => {
        return None;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何分配给匹配分支内的匹配表达式中使用的变量? 的相关文章

随机推荐

  • 类是结构体还是结构体指针

    如果我没记错的话 结构意味着对象 结构指针意味着指向对象的指针 对吗 在一篇文章中 它说类是结构 这意味着它们是对象 Filter the list of all classes The traditional definition of
  • 从 Facebook 获取电子邮件 - FB android SDK

    我使用以下代码从 Facebook 获取用户的电子邮件和姓名 protected void onCreate Bundle savedInstanceState Display page setContentView R layout ac
  • 致命错误:sys/socket.h:32位上没有这样的文件或目录

    当使用 32 位编译我的程序时 gcc m32 program c o program 我收到以下错误致命错误 sys socket h 没有这样的文件或目录 但与 gcc program c o program 效果很好 有什么解决方法吗
  • KSoap2 和 KvmSerialized - 如何发送复杂的对象,如 Stringarrays

    我想将一个复杂的对象从我的 Ksoap 客户端发送到我的 Web 服务 它是我的类别类别的一个对象 该代码基于本教程的示例 http seesharpgears blogspot de 2010 10 ksoap android web s
  • 如何在Hive中获取数组中的前n个元素

    我使用 split 函数在 Hive 中创建一个数组 如何从数组中获取前 n 个元素 并且我想遍历子数组 代码示例 select col1 from table where split col2 0 5 0 5 看起来像 python 风格
  • 如何找到符号的完全限定名称空间?

    如果我有一个符号 其名称空间是别名 例如 q w 我如何找到它的实际名称空间 例如actual namespace w 我知道resolve会给我完全限定的 var 但我不知道如何获取 var 的命名空间 我能做的最好的事情就是 defn
  • MATLAB 中的矩阵运算

    我正在尝试简化我的代码 但遇到了一个小问题 让 v 1 2 3 a1 4 5 6 a2 7 8 9 A a1 a2 我的目标是计算 u v a1 v a2 仅使用v一度 这可能吗 是的 你可以使用bsxfun 例如 u bsxfun tim
  • `use std::io::Result as IOResult;` 比 `use std::io;` 仅仅引用 Rust 中的 `io::Result` 更高效吗?

    在学习 Rust 的过程中 我看到了人们导入库的多种方式 例如std io Result 例如 use std io Result as IOResult and pub type IOResult
  • R 中的表情符号 [UTF-8 编码]

    我正在尝试对 R 进行表情符号分析 我存储了一些带有表情符号的推文 这是我要分析的推文之一 gt tweetn2 1 Programme du week end xed xa0 xbd xed xb2 x83 xed xa0 xbc xed
  • Rails 迁移抱怨使用回形针的未定义方法“附件”

    Lemmie 在开头说我对 Rails 还很陌生 我们的应用程序使用回形针 3 2 4 来管理附件 像往常一样 我生成了一个类似于以下内容的迁移 class AddAttachmentPhotoToPhpfoxUsers lt Active
  • 是否有必要在 C# 中显式删除事件处理程序

    我有一堂课提供一些活动 该类是全局声明的 但不是在该全局声明上实例化的 它是根据需要在需要它的方法中实例化的 每次方法中需要该类时 都会对其进行实例化并注册事件处理程序 在方法超出范围之前是否有必要显式删除事件处理程序 当方法超出范围时 类
  • 为 Windows 上的 Lua 构建 lua 文件系统

    我对构建 makefile 没有任何线索 我正在尝试在 Windows 7 x86 中构建 luafilesystem 以便与 Lua for Windows 一起使用 我已经在互联网上搜索了教程 但我就是无法弄清楚 我在开发人员命令提示符
  • 如何使用 UIImagePickerController 显示所有相机控件?

    使用 UIImagePickerController 时 我无法显示相机控件 具体来说 我需要能够在慢动作 视频 照片 方形和全景之间进行选择 我使用的代码的基本部分是 UIImagePickerController pc UIImageP
  • 从 C# 修改任何窗口的不透明度

    是否可以从 C 修改所有打开的窗口的不透明度 我在 google 上搜索了最小化窗口 我发现这可以通过 pInvoke 调用实现 它甚至起作用了 同样 是否可以从 C 更改所有打开的窗口的不透明度 另外 我不喜欢 MFC 的东西 还有什么工
  • 测量执行单个指令的时间

    有没有办法使用 C 或汇编程序甚至 C 来准确测量执行 ADD 指令所需的时间 是的 有点 但它并不平凡 并且产生的结果是almost毫无意义 至少在最现代的处理器上是这样 在相对较慢的处理器上 例如 从英特尔系列中的原始奔腾处理器开始 在
  • 将 tf.keras.utils.image_dataset_from_directory 与标签列表一起使用

    我有目录示例中相应数量的文件的标签列表 1 2 3 train ds tf keras utils image dataset from directory train path label mode int labels train la
  • raw 文件夹中文本文件中的除号

    我的 android 的 txt 文件中有 当这个除法符号显示在 Android 设备上时 我看到 更糟糕的是 我的笔记本电脑键盘上没有除号 我使用了维基百科上的标志 猜猜我该如何解决这个问题 您应该对任何符号 例如此处的除号 使用 Uni
  • 如何使用jquery设置多个CSS显示属性值

    好吧 这让我有点抓狂 我正在使用 jQuery css 方法try设置类所需的多个 Flexbox 显示属性 问题是 它只保留最后一个 关于如何使用 jQuery 执行此操作的任何想法 或者这是不可能的 到目前为止 这是我尝试过的 depa
  • 如何指定CSS类的顺序?

    我对 CSS 和class属性 我一直认为 我在属性值中指定多个类的顺序是有意义的 后面的类可以 应该覆盖前面的定义 但这似乎不起作用 这是一个例子
  • 如何分配给匹配分支内的匹配表达式中使用的变量?

    我正在尝试实现一个通用功能join 它可以在任何迭代器的迭代器上工作 我的借用检查器有问题match里面的表达式next 方法实施 这是我的代码的简化版本 pub struct Join i where I Iterator I Item