代码之家  ›  专栏  ›  技术社区  ›  Afshin Mehrabani Mohd Jafar

防锈封闭是如何工作的,它是如何执行封闭的?

  •  4
  • Afshin Mehrabani Mohd Jafar  · 技术社区  · 7 年前

    它是否创建一个新线程,然后在新线程内执行该匿名函数?

    我注意到,当我处理结案时,有许多所有权/借款限制。例如,如果我有 Fn() , I cannot pass a mutable variable inside the closure or it needs to be wrapped with a Mutex :

    fn helloworld(f: &Fn(f64)) {
        f(42f64);
    }
    
    pub fn main() {
        let mut killer = 2;
        helloworld(&|n| {
            println!("{}", n);
            killer += 1;
        });
    }
    

    如果一个闭包可能是不安全的,那么在幕后会发生异步或并行的事情,这就是为什么Rust编译器不允许我编译这样的代码。

    1 回复  |  直到 7 年前
        1
  •  22
  •   Shepmaster Tim Diekmann    7 年前

    这个问题有两个层次。

    首先,Rust中的闭包只是一个匿名定义的类型,它实现了一个或多个“可调用”特征。例如:

    fn main() {
        let a = 6;
        let closure = |b| {
            println!("product is: {}", a * b);
        };
        closure(7);
    }
    

    fn main() {
        let a = 6;
        let closure = {
            struct Closure<'a> {
                a: &'a i32,
            }
            impl<'a> Fn<(i32,)> for Closure<'a> {
                extern "rust-call" fn call(&self, (b,): (i32,)) {
                    println!("product is: {}", (*self.a) * b);
                }
            }
            impl<'a> FnMut<(i32,)> for Closure<'a> {
                extern "rust-call" fn call_mut(&mut self, args: (i32,)) {
                    self.call(args)
                }
            }
            impl<'a> FnOnce<(i32,)> for Closure<'a> {
                type Output = ();
                extern "rust-call" fn call_once(self, args: (i32,)) {
                    self.call(args)
                }
            }
            Closure {
                a: &a,
            }
        };
        FnOnce::call_once(closure, (7,));
    }
    

    笔记 :上述代码依赖于不稳定的内部细节,无法在稳定的编译器上运行。仅供解释;你应该 自己使用这种模式。

    这将我们带到第二层,这就是为什么您的 具体的 代码不起作用: Fn , FnMut FnOnce 特征(在问题的答案中解释) When does a closure implement Fn, FnMut and FnOnce? &Fn(f64) ,您只接受需要对其上下文进行不可变访问的闭包。

    如果希望闭包能够改变其上下文,则需要使用 FnMut公司 FnOnce公司