【问题标题】:Closure requires unique access to lambda function闭包需要对 lambda 函数的唯一访问
【发布时间】:2014-11-15 05:25:31
【问题描述】:

我正在学习 Rust,并且已经实现了一些简单的代码来试验闭包 - 但是我遇到了借用检查器的问题,我不确定如何解决。

编译如下函数时

fn twice(x:int, f:|int| -> int) -> int {
    f(f(x))
}

我收到以下错误

closure requires unique access to `f` but it is already borrowed

我正在阅读该指南,并且对借用检查器不喜欢这个问题的原因有一定的了解 - 但我不确定如何解决它。

我可以通过首先将第一次调用的结果分配给一个临时变量,然后再次调用f(..) 来解决这个问题。然而,这感觉不雅。

是否有更简洁/更好的编写f(f(x)) 的方法,或者有什么方法可以让编译器相信这是安全的?

【问题讨论】:

    标签: rust borrow-checker


    【解决方案1】:

    完整的错误信息是:

    <anon>:2:7: 2:8 error: closure requires unique access to `f` but it is already borrowed
    <anon>:2     f(f(x))
                   ^
    <anon>:2:5: 2:6 note: previous borrow of `f` occurs here; the unique capture prevents subsequent moves or borrows of `f` until the borrow ends
    <anon>:2     f(f(x))
                 ^
    <anon>:2:12: 2:12 note: previous borrow ends here
    <anon>:2     f(f(x))
                       ^
    

    也就是说,外部调用在某种意义上是保留f 并阻止它首先被使用。这与issue #6268 非常相似,后者关注的是方法而不是闭包。

    正如您所说,使用临时解决方案是一种解决方法,也是最合理的解决方法。

    fn twice(x:int, f:|int| -> int) -> int {
        let y = f(x);
        f(y)
    }
    

    【讨论】:

    • 谢谢。你知道这是故意的语言的一部分,还是我们将在某个时候清理的借用检查器中的边缘情况?
    • 这当然必须解决。
    • @JamesDavies,主要是一个边缘案例(例如,参见我参考的问题)。
    【解决方案2】:

    在现代 Rust 中,原始代码按原样编译:

    fn twice(x: i32, f: impl Fn(i32) -> i32) -> i32 {
        f(f(x))
    }
    
    fn main() {
        twice(42, |i| dbg!(i));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-20
      • 2011-07-23
      • 2022-01-24
      相关资源
      最近更新 更多