【问题标题】:Rust cloning HashMap<String, Object> without moving into closureRust 克隆 HashMap<String, Object> 而不进入闭包
【发布时间】:2021-12-31 08:25:24
【问题描述】:

我正在尝试使用 rust 编写自己的编程语言,并且大多数功能都已完成,所以我认为我可以在 UnknownIdentifier 错误中添加能够找到与用户想要的任何内容最接近的匹配项的能力

然而,在我找到最接近的匹配之前,我发现克隆 HashMap 会将其移动到闭包中

ErrorGenerator::error 函数:

#[allow(non_snake_case)]
mod ErrorGenerator {
    pub fn error(name: &str, explanation: &str, line: usize, col: usize, file: String, after_f: Box<dyn Fn() -> ()>) -> ! {
        eprintln!("\n[ERROR] {}, Line {:?}, Column {:?}", file, line, col);
        eprintln!("    {}: {}", name, explanation);
        after_f();
        exit(1);
    }
}
ErrorGenerator::error(
    "UnknownIdentifier",
    &format!("unknown identifier: `{}`, this identifier could not be found", tokenc.repr()),
    tokenc.line,
    tokenc.col,
    tokenc.file,
    Box::new(||{
        let mut hashc: Vec<String> = hashs.clone().into_keys().collect();
        hashc.sort();
    }),
);

这是它给出的错误:

error[E0597]: `hashs` does not live long enough
    --> src/runtime/runtime.rs:960:70
     |
959  |                                       Box::new(||{
     |                                       -        -- value captured here
     |  _____________________________________|
     | |
960  | |                                         let mut hashc: Vec<String> = hashs.clone().into_keys().collect();
     | |                                                                      ^^^^^ borrowed value does not live long enough
961  | |                                         hashc.sort();
962  | |                                     }),
     | |______________________________________- cast requires that `hashs` is borrowed for `'static`
...
1203 |       }
     |       - `hashs` dropped here while still borrowed

问题的解决方案可能是:

  • 一种在“静态生命周期”中将方法中创建的可变变量借入闭包的方法 或
  • 一种克隆 HashMap 而不将其移动到闭包中的方法

你可以在https://github.com/kaiserthe13th/tr-lang/tree/unknown-id-err-impl找到完整的代码

【问题讨论】:

    标签: rust hashmap closures borrow-checker cloning


    【解决方案1】:

    发生的情况是编译器没有克隆hashs,然后将克隆传递给您的回调;相反,它将hashs 的引用传递给您的回调并将其克隆在回调中

    但是,回调必须是'static,如果它包含对包含函数的引用,则不是!所以编译器在抱怨。

    您想要的是在 之前 克隆 hashmap,然后将 克隆 传递给回调。喜欢:

    ErrorGenerator::error(
        "UnknownIdentifier",
        &format!("unknown identifier: `{}`, this identifier could not be found", tokenc.repr()),
        tokenc.line,
        tokenc.col,
        tokenc.file,
        {
            let hashc = hashs.clone();
            Box::new(|| {
                let mut hashc: Vec<String> = hashc.into_keys().collect();
                hashc.sort();
            })
        },
    );
    

    如果您这样做,您还将认识到关闭需要为FnOnce(),因为您要搬出hashc (.into_keys())。所以after_f: Box&lt;dyn FnOnce()&gt;

    【讨论】:

    • 非常感谢,我尝试了同样的方法,但没有使用 FnOnce,因为我猜我对闭包不够熟悉
    • 我会把你放在项目的感谢部分
    • 这个答案看起来不错。一个重要的事情是克隆 HashMap 将克隆它的键、值和哈希。如果您需要的是密钥的克隆,那可能效率不高。我认为您可以直接克隆键,而不是哈希图,并将克隆的键移动到闭包中。这样,就不需要 FnOnce。
    • @Joe_Jingyu 是的,你是对的,但我也许 OP 需要对 hashmap 执行更多工作,所以我只是回答了这个问题。如果没有,更好的用法是在闭包之外做let hashc: Vec&lt;String&gt; = hashs.keys().cloned().collect();
    猜你喜欢
    • 1970-01-01
    • 2013-06-30
    • 2012-10-13
    • 2014-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-16
    相关资源
    最近更新 更多