关闭需要独特的访问

时间:2014-05-13 06:43:46

标签: closures rust

我试图通过在以下代码中使用闭包来避免重复自己:

fn add_raw(&mut self, pair: RawLinkPair) {
    let convert = |raw: &RawLink| {
        Link{
            id:         self.get_or_create(raw.name).id,
            flow:       raw.flow,
        }
    };

    println!("Hive received pair: {}", pair);
    let parent = convert(&pair.parent);
    let child = convert(&pair.child);
    self.link_concepts(parent, child);
}

这不起作用。它给了我这个错误:

hive.rs:64:9: 64:13 error: cannot borrow `*self` as mutable because previous closure requires unique access
hive.rs:64         self.link_concepts(parent, child);
                   ^~~~
hive.rs:55:23: 60:10 note: previous borrow of `self` occurs here due to use in closure; the unique capture prevents subsequent moves or borrows of `self` until the borrow ends
hive.rs:55         let convert = |raw: RawLink| {
hive.rs:56             Link{
hive.rs:57                 id:         self.get_or_create(raw.name).id,
hive.rs:58                 flow:       raw.flow,
hive.rs:59             }
hive.rs:60         };
hive.rs:65:6: 65:6 note: previous borrow ends here
hive.rs:54     fn add_raw(&mut self, pair: RawLinkPair) {
...
hive.rs:65     }
               ^
error: aborting due to previous error

在这种情况下,我实际上并没有为自己节省太多的击键次数。我可以手动输入所有内容,它可以正常工作:

fn add_raw(&mut self, pair: RawLinkPair) {
    let parent = Link {
        id:     self.get_or_create(pair.parent.name).id,
        flow:   pair.parent.flow,
    };

    let child = Link {
        id:     self.get_or_create(pair.child.name).id,
        flow:   pair.child.flow,
    };

    self.link_concepts(parent, child);
}

我理解错误(所以我认为),但是:

  1. 原则上在这里使用闭包有什么问题吗?或者我写错了吗?
  2. 是否有更惯用的方式来写这个,或者至少,我如何满足借阅检查器?
  3. 这可能是一个暗淡的问题,但为什么借用只是在最后一次调用convert后立即结束?这对我来说似乎很奇怪,特别是当我将它与底部版本进行比较时,它最终会采用相同的步骤减去封闭。

1 个答案:

答案 0 :(得分:2)

你应该能够像这样修理它(你称之为“满足借用检查器”):

fn add_raw(&mut self, pair: RawLinkPair) {
    let (parent, child) = {
        let convert = |raw: RawLink| {
            Link{
                id:         self.get_or_create(raw.name).id,
                flow:       raw.flow,
            }
        };

        (convert(pair.parent.clone()), convert(pair.child.clone()))
    };
    self.link_concepts(parent, child);
}

据我所知,这在当前Rust中是无法形容的(即没有闭包)。闭包通过&only引用来获取它们的环境(目前它只适用于编译器),它禁止在超出范围之前引用其他引用。它就像&mut引用,但不一定与可变性相关。闭包环境捕获在创建时发生,因此捕获的生命周期延伸到函数的末尾,因此您将收到错误。

为什么闭包应该通过我不知道的唯一引用来占用他们的环境。