zoukankan      html  css  js  c++  java
  • Cannot move out of captured outer variable in an Fn closure

    https://stackoverflow.com/questions/50000453/cannot-move-out-of-captured-outer-variable-in-an-fn-closure

    fn make_adder(x: String) -> Box<Fn() -> String> {
        Box::new(|| x)
    }
    
    fn main() {
        make_adder(String::from("a"));
    }
    

    This results in this error:

    error[E0507]: cannot move out of captured outer variable in an `Fn` closure
     --> src/main.rs:2:17
      |
    1 | fn make_adder(x: String) -> Box<Fn() -> String> {
      |               - captured outer variable
    2 |     Box::new(|| x)
      |                 ^ cannot move out of captured outer variable in an `Fn` closure
    

    How can I make it correct?


    A closure which implements Fn can be called multiple times (the receiver parameter is &self, an immutable reference to the closure):

    fn call_multiple_times<F: Fn(u8) -> i32>(f: F) {
        // Works! We can call the closure mutliple times
        let a = f(1);
        let b = f(27);
        let c = f(31);
    }
    

    This means that with your closure Fn() -> String, you could do this:

    let s1 = adder();
    let s2 = adder();
    

    Now you would have two Strings although you only started with one! Magic? You can of course get another string by cloning the original string, but we don't do that here. So it clearly can't work.


    You can fix that in two ways. Either you don't need your closure to be called multiple times. In that case you can simply change Fn to FnOnce (a less demanding trait). An FnOnce closure can only be called ... well ... once. This works:

    fn make_adder(x: String) -> Box<FnOnce() -> String> {
        Box::new(|| x)
    }
    

    On the other hand, maybe you want the closure to be called multiple times and always want to return a new clone of the string. You can do that like this:

    fn make_adder(x: String) -> Box<Fn() -> String> {
        Box::new(move || x.clone())
    }
    

    Here we added a .clone() call (since in Rust, deep clones are never implicit!) and we added the move keyword. The latter is necessary to explicitly move the string x into the closure, not just borrow it.

  • 相关阅读:
    以相同类型的一个对象初始化另一个对象
    java之StringBuilder类详解
    java之StringBuffer类详解
    jquery在线引用地址
    java之抽象类
    Oracle动态执行表不可访问
    libvirt-qemu-TLS加密虚拟机传输实例分析
    查看系统是虚拟机还是物理机
    WorkStation 虚拟机迁移到 ESXi
    Django入门------常见问题
  • 原文地址:https://www.cnblogs.com/dhcn/p/14465708.html
Copyright © 2011-2022 走看看