如何从关闭中获取移动值的所有权?

时间:2017-12-05 04:45:36

标签: rust

考虑以下计划:

fn primes_up_to(n: usize) -> Vec<usize> {
    let mut ans = Vec::with_capacity(n);

    if n < 2 {
        return ans;
    }

    ans.push(2);

    // https://doc.rust-lang.org/1.22.0/book/first-edition/closures.html#closures-and-their-environment
    // The closure needs ownership of vec to access elements
    let is_prime = |n: usize| -> bool {
        for x in ans {
            if x * x > n {
                break;
            }

            if n % x == 0 {
                return false;
            }
        }

        true
    };

    let mut i = 3;
    while i <= n {
        if is_prime(i) {
            ans.push(i);
        }

        i += 2;
    }

    ans
}

fn main() {
    println!("{:?}", primes_up_to(23));
}

playground

编译上面的代码会产生以下编译错误:

error[E0382]: use of moved value: `is_prime`
  --> src/main.rs:28:12
   |
28 |         if is_prime(i) {
   |            ^^^^^^^^ value moved here in previous iteration of loop
   |
note: closure cannot be invoked more than once because it moves the variable `ans` out of its environment
  --> src/main.rs:13:18
   |
13 |         for x in ans {
   |                  ^^^

error[E0382]: use of moved value: `ans`
  --> src/main.rs:29:13
   |
12 |     let is_prime = |n: usize| -> bool {
   |                    ------------------ value moved (into closure) here
...
29 |             ans.push(i);
   |             ^^^ value used here after move
   |
   = note: move occurs because `ans` has type `std::vec::Vec<usize>`, which does not implement the `Copy` trait

error[E0382]: use of moved value: `ans`
  --> src/main.rs:35:5
   |
12 |     let is_prime = |n: usize| -> bool {
   |                    ------------------ value moved (into closure) here
...
35 |     ans
   |     ^^^ value used here after move
   |
   = note: move occurs because `ans` has type `std::vec::Vec<usize>`, which does not implement the `Copy` trait

我知道一个可能的解决方案是将ans&ans)的不可变引用传递给is_primeans的所有权转换为is_prime的惯用方式是什么?每次拨打is_primeis_prime退出时都会退出?

2 个答案:

答案 0 :(得分:3)

  

如何从闭包中获取移动值的所有权

你没有

一旦所有权转移,它就消失了。 “让它回来”的唯一方法是让现在拥有的东西将其转回。出于这个原因,某些类型具有DirectoryChooser directoryChooser = new DirectoryChooser(); File selectedDirectory = directoryChooser.showDialog(stage); if(selectedDirectory == null){ //No Directory selected }else{ System.out.println(selectedDirectory.getAbsolutePath()); } 方法。其他类型有相同的方法。

根据定义,闭包的唯一接口是调用它的能力。方法没有其他可能性。

你可以在完成后返回捕获的值,但这对你的情况没有帮助,因为你需要多次调用闭包 - 你无法返回它,因为将来可能需要它。

答案 1 :(得分:1)

您的代码存在一些问题:

$datArr = array(
    array(
        "name" => "Ram",
        "id" => 1,
        "date" => "12/04/2017 05:31:57"
    ),
    array(
        "name" => "Rahim",
        "id" => 5,
        "date" => "12/03/2017 12:31:57"
    ),
    array(
        "name" => "Raj",
        "id" => 4,
        "date" => "12/04/2017 05:31:57"
    )
);
  

闭包不能多次调用,因为它会移动变量   for x in ans { 退出其环境:

每个ans

迭代器无效

所以你应该在这一行中完全借用ans.push(i);

ans
然后把它还给下一行:

if is_prime(i) {

解决方案是将其作为参数传递:

ans.push(i);

playground

或试试这个,它在夜间频道的发布模式中具有与上述相同的fn primes_up_to(n: usize) -> Vec<usize> { let mut ans = Vec::with_capacity(n); if n < 2 { return ans; } ans.push(2); let is_prime = |n: usize, v: &[usize]| -> bool { for x in v { if x * x > n { break; } if n % x == 0 { return false; } } true }; let mut i: usize = 3; while i <= n { if is_prime(i, &ans) { ans.push(i); } i += 2; } ans } fn main() { println!("{:?}", primes_up_to(23)); } 足迹:

ASM

playground

输出:

fn primes_up_to(n: usize) -> Vec<usize> {
    let mut ans = Vec::with_capacity(n);
    if n < 2 {
        return ans;
    }
    ans.push(2);
    let is_prime = |n: usize, v: &Vec<usize>| -> bool {
        for x in v {
            if x * x > n {
                break;
            }
            if n % x == 0 {
                return false;
            }
        }
        true
    };
    let mut i: usize = 3;
    while i <= n {
        if is_prime(i, &ans) {
            ans.push(i);
        }
        i += 2;
    }
    ans
}

fn main() {
    println!("{:?}", primes_up_to(23));
}

请参阅:Move semanticsBorrowing