首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从结构的vec中提取vec

从结构的vec中提取vec
EN

Stack Overflow用户
提问于 2022-07-06 19:33:27
回答 1查看 65关注 0票数 0

我正在为一种玩具语言编写编译器,我希望能够检查每个文件上的错误。我有一个MooFile结构,它有一个Vec<anyhow::Error>,当遇到错误时,我会在那里放置错误。现在,我想遍历这些文件,获取错误,并将其压缩到一个单独的vec中,以便从编译器返回,但我遇到的是借阅检查器。我将发布我的各种尝试,但他们总是遇到类似的问题。

代码语言:javascript
复制
fn compile(&mut self) -> Result<(), Vec<Error>> {
    ...
    // Check for errors
    let has_errors = self.files
        .iter()
        .map(|file| file.has_errors())
        .reduce(|acc, value| acc | value)
        .unwrap_or(false);

     if has_errors {
        let mut errors = vec![];
        self.files
            .iter()
            .for_each(|&mut file| errors.append(&mut file.errors));

        Err(errors)
    } else {
        Ok(())
    }
}
代码语言:javascript
复制
error[E0596]: cannot borrow `file.errors` as mutable, as it is behind a `&` reference
  --> src\lib.rs:62:48
   |
62 |                 .for_each(|file| errors.append(&mut file.errors));
   |                            ----                ^^^^^^^^^^^^^^^^ `file` is a `&` reference, so the data it refers to cannot be borrowed as mutable
   |                            |
   |                            help: consider changing this to be a mutable reference: `&mut MooFile`
代码语言:javascript
复制
fn compile(&mut self) -> Result<(), Vec<Error>> {
    ...
    // Check for errors
    let has_errors = self.files
        .iter()
        .map(|file| file.has_errors())
        .reduce(|acc, value| acc | value)
        .unwrap_or(false);

    if has_errors {
        let mut errors = vec![];
        self.files
            .into_iter()
            .for_each(|mut file| errors.append(&mut file.errors));

        Err(errors)
    } else {
        Ok(())
    }
}
代码语言:javascript
复制
error[E0507]: cannot move out of `self.files` which is behind a mutable reference
   --> src\lib.rs:63:13
    |
63  |             self.files
    |             ^^^^^^^^^^ move occurs because `self.files` has type `Vec<MooFile>`, which does not implement the `Copy` trait
64  |                 .into_iter()
    |                  ----------- `self.files` moved due to this method call
代码语言:javascript
复制
fn compile(&mut self) -> Result<(), Vec<Error>> {
    ...
    // Check for errors
    let errors: Vec<Error> = self.files
        .iter()
        .map(|file| file.errors)
        .flatten()
        .collect();

    if errors.len() > 0 {
        Err(errors)
    } else {
        Ok(())
    }
}
代码语言:javascript
复制
error[E0507]: cannot move out of `file.errors` which is behind a shared reference
  --> src\lib.rs:54:25
   |
54 |             .map(|file| file.errors)
   |                         ^^^^^^^^^^^ move occurs because `file.errors` has type `Vec<anyhow::Error>`, which does not implement the `Copy` trait

For more information about this error, try `rustc --explain E0507`.
error: could not compile `moo2` due to previous error

我觉得必须有某种惯用的方式来做这种我错过的事情。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-06 20:08:42

这些错误大多来自您如何创建迭代器。如果假设xVec<Y>

  • x.iter():消耗&x,创建&Y.
  • x.iter_mut():迭代器,消耗&mut x,创建&mut Y.
  • x.into_iter():迭代器,消耗整个Vec<Y>的所有权,创建拥有Y.

的迭代器。

当您需要可变引用( .iter() )时,第一个版本使用.iter_mut()。第二种方法是在需要可变引用( .into_iter() )时使用.iter_mut()。第三种方法使用.iter(),当您试图通过处理文件来声明错误的所有权时(.into_iter(),但是您不能在没有问题的情况下删除self.files )。

这里有一种方法,您可以Clone错误而不将它们从每个file中移出。

代码语言:javascript
复制
let mut errors = Vec::new();

self.files.iter()
    .filter(|file| file.has_errors())
    .foreach(|file| errors.extend_from_slice(&file.errors));

if has_errors {
    return Err(errors)
}
Ok(())

或者您可以使用drain将它们放入一个新的Vec中。这个版本也使用any看起来更干净,但效率不高。

代码语言:javascript
复制
if self.files.iter().any(|f| f.has_errors()) {
    let mut errors = Vec::new();

    for file in &mut self.files {
        errors.extend(file.errors.drain(..));
    }

    return Err(errors)
}

Ok(())
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72888978

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档