对FnMut闭包中的值捕获的upvar进行变换

时间:2015-05-05 13:03:29

标签: closures rust

我正在尝试创建一个简单的程序,其中包含一个逐渐清空自己的集合的闭包:

fn main() {
    let vector = vec![1, 2, 3];

    let mut allow_once = move |i: &i32| -> bool {
        if let Some(index) = vector.position_elem(i) {
            vector.remove(index);
            return true
        }
        false
    };

    for e in &[1, 2, 3, 1, 2, 3] {
        let is_in = if allow_once(e) { "is" } else { "is not" };
        println!("{} {} allowed", e, is_in);
    }
}

似乎犹太洁食(对我来说),但是rustc抱怨(每晚):

<anon>:6:13: 6:19 error: cannot borrow captured outer variable in an `FnMut` closure as mutable
<anon>:6             vector.remove(index);
                     ^~~~~~

我希望这个问题可能是一个令人沮丧的问题。也就是说,虽然实现从未违反别名XOR突变原则,但可能是因为rustc没有意识到这一点。

因此:

  1. 这是暂时的限制/错误还是内在的?
  2. 如何尽可能高效地创建具有可变环境的闭包?
  3. 注意:通过引用捕获不是一个选项,我希望能够移动闭包。

1 个答案:

答案 0 :(得分:6)

事实上,这个问题很容易解决。只需将mut限定符添加到vector

fn main() {
    let mut vector = vec![1, 2, 3];

    let mut allow_once = move |i: &i32| -> bool {
        if let Some(index) = vector.position_elem(i) {
            vector.remove(index);
            true
        } else { false }
    };

    for e in &[1, 2, 3, 1, 2, 3] {
        let is_in = if allow_once(e) { "is" } else { "is not" };
        println!("{} {} allowed", e, is_in);
    }
}

(工作代码here

它与以往一样具有相同的可变性规则 - 为了改变某些东西,它必须在某处具有mut,无论是在其变量声明中还是在其类型中(&mut)。