Rust 如何从闭包中获得已移动值的所有权?

Rust 如何从闭包中获得已移动值的所有权?,rust,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-

考虑以下计划:

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));
}
fn素数到(n:usize)->Vec{
设mut ans=Vec::具有_容量(n);
如果n<2{
返回ans;
}
ans.push(2);
// https://doc.rust-lang.org/1.22.0/book/first-edition/closures.html#closures-以及他们的环境
//关闭需要vec的所有权才能访问元素
让is|u prime=|n:usize->bool{
对于ans中的x{
如果x*x>n{
打破
}
如果n%x==0{
返回false;
}
}
真的
};
设muti=3;
而我src/main.rs:28:12
|
28 |如果是素数(i){
|^^^^^^^^^值在循环的上一次迭代中移动到此处
|
注意:闭包不能被多次调用,因为它将变量“ans”移出其环境
-->src/main.rs:13:18
|
13 |对于ans中的x{
|                  ^^^
错误[E0382]:使用移动值:`ans`
-->src/main.rs:29:13
|
12 | let is|u prime=| n:usize |->bool{
|--------------此处已将值移到(闭包中)
...
29 | ans.push(i);
|^^^移动后此处使用的值
|
=注意:发生移动是因为`ans`的类型为`std::vec::vec`,而该类型不实现`Copy`特性
错误[E0382]:使用移动值:`ans`
-->src/main.rs:35:5
|
12 | let is|u prime=| n:usize |->bool{
|--------------此处已将值移到(闭包中)
...
35 | ans
|^^^移动后此处使用的值
|
=注意:发生移动是因为`ans`的类型为`std::vec::vec`,而该类型不实现`Copy`特性

我知道一个潜在的解决方案是将一个不可变的引用传递给
ans
&ans
)to
is_prime
ans
的所有权传递到
is_prime
并在每次调用
is_prime
时退出时返回的惯用方式是什么?

您的代码存在一些问题,具体如下:

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

迭代器对每个
ans.push(i);

因此,您应该借用这行中的
ans

if is_prime(i) {
然后将其返回到下一行:

ans.push(i);
解决方案是将其作为参数传递:

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));
}
()

输出:

[2,3,5,7,11,13,17,19,23]
看,还有

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

你不知道

一旦所有权被转移,它就消失了。“找回它”的唯一方法是让现在拥有它的东西把它转移回来。一些类型有一个
到\u-inner
方法,正是出于这个原因。其他类型有相同的方法

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


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

此时闭包没有捕获任何内容。因此可以用函数
fn is_prime(n:usize,v:&[usize]替换它)->bool{/…
是素数(i,&ans)
更简洁。
Vec
实现了
Deref
,因此
&ans
被强制为
,[usize]
。虽然这确实修复了示例代码,但我认为它实际上没有回答问题@Stefan:解释Added@a-r我理解了将向量作为参数传递给闭包以实现这一点。我特别想了解的是,如果闭包不修改向量,是否应该有一种方法让它只捕获数据的引用而不获取所有权,因为闭包不需要所有权——它来到这里,因为它没有做任何事情来修改向量存储的数据,并且添加对向量的引用作为参数首先会使闭包的目的无效。>您无法返回它,因为将来可能需要它。在我看来,如果闭包返回其捕获的值,则可以重新创建租借值的所有权,当再次调用时,只需再次捕获该值。这有什么问题吗?@JiacaiLiu我不完全同意你的建议。如果闭包需要一个值才能工作并返回该值的所有权,那么闭包就不能再存在。是的,你可以用该值重新创建闭包,但这是错误的这将是一堆重复的代码,忽略了闭包的意义,所以我不明白为什么它会有用。
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));
}