Rust 借用闭包中的可变引用对向量进行排序

Rust 借用闭包中的可变引用对向量进行排序,rust,reference,closures,borrow-checker,borrowing,Rust,Reference,Closures,Borrow Checker,Borrowing,虽然我了解Rust的内存安全方法、所有权概念,并且一般来说对引用没有问题,但我仍在努力弄清楚Rust希望我如何解决一个看似微不足道的问题 这段代码只是一个简单的例子 结构: pub struct S { value: Option<i8>, } 抛出: error[E0596]: cannot borrow `**a` as mutable, as it is behind a `&` reference --> src/main.rs:27:20

虽然我了解Rust的内存安全方法、所有权概念,并且一般来说对引用没有问题,但我仍在努力弄清楚Rust希望我如何解决一个看似微不足道的问题

这段代码只是一个简单的例子

结构:

pub struct S {
    value: Option<i8>,
}
抛出:

error[E0596]: cannot borrow `**a` as mutable, as it is behind a `&` reference
  --> src/main.rs:27:20
   |
27 |     v.sort_by( |a, b| a.get_v().cmp(&b.get_v()) );
   |                 -     ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
   |                 |
   |                 help: consider changing this to be a mutable reference: `&mut &mut S`
我最初的想法是,首先拥有可变引用向量将允许比较函数使用可变引用。然而,我的getter函数将可变引用借用到可变引用,这就是为什么错误显示
不能借用'**a'

帮助建议更改
|a、b |
,使它们成为
和mut&mut S
引用

&mut&mut
&mut
相同吗?
这是否意味着我应该将其更改为
|mut a:&&mut S,mut b:&&mut S |

排序依据()中的闭包具有签名
FnMut(&T,&T)->排序
,因为项目在排序期间必须是不可变的。如果可以在排序过程中对项目进行变异,那么您将如何判断集合实际排序的时间?无法验证排序的正确性

此外,
sort\u by
是一种基于比较的排序,这意味着它将至少访问集合中的每个项一次,因此在整个排序过程中,每个项都将被初始化,因此在这种情况下,使用惰性初始化getter并不能真正获得任何东西

如果出于某种原因,您希望出于其他原因继续使用惰性初始化getter,那么我的建议是在对所有项进行排序之前初始化它们:

使用rand::Rng;
发布结构{
价值:期权,
}
impl S{
fn获取值(&mut self)->i8{
如果让一些(v)=自我价值{
返回v;
}
设v=rand::thread_rng().gen:();
自我价值=一些(v);
v
}
}
fn main(){
设muta=S{value:None};
设mutb=S{value:None};
设mutc=S{value:None};
让mut v=vec![&mut a,&mut b,&mut c];
//初始化所有项目,这就是
//如果允许的话,按以下方式进行
//不管怎样,在排序过程中对项目进行变异
v、 iter_mut()。对于每个(| i |{
i、 获取_值();
});
//对初始化的项进行排序,而不对其进行变异
v、 排序依据(| a,b | a.value.cmp(&b.value));
}

假设您的示例已简化,并且实际代码中实际上需要可变性,这可能是内部可变性的一个很好的例子,例如使用
单元格

use std::cell::Cell;

pub struct S {
    value: Cell<Option<i8>>,
}

&&mut x
不能变异,如果可以,您可以分割一个可变引用,从而导致竞争条件。遗憾的是,只有在Rust中,排序才是不可变的引用,因为如果值在排序过程中发生变化,可能会打乱整个过程。您可能需要考虑使用诸如<>代码> STD::Cys::Cys<代码>内部可变性,因为您的情况是完全安全的(一旦获得值,它就永远不会改变)。如果您的值没有被创建,直到它被访问,然后不改变,考虑使用您是正确的,在这种情况下,我不会用惰性初始化获得任何东西。我仍然很困扰,我不知道怎么做。我现在明白了,谢谢你的例子。看来我停止阅读有点太早了。包装在实践中似乎比我准备接受的更重要。
error[E0596]: cannot borrow `**a` as mutable, as it is behind a `&` reference
  --> src/main.rs:27:20
   |
27 |     v.sort_by( |a, b| a.get_v().cmp(&b.get_v()) );
   |                 -     ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
   |                 |
   |                 help: consider changing this to be a mutable reference: `&mut &mut S`
use std::cell::Cell;

pub struct S {
    value: Cell<Option<i8>>,
}
impl S {
    fn get_value(&self) -> i8 {
        if let Some(v) = self.value.get() {
            return v;
        }

        let v = rand::thread_rng().gen::<i8>();
        self.value.set(Some(v));
        v
    }
}
fn main() {
    let a = S { value: Cell::default() };
    let b = S { value: Cell::default() };
    let c = S { value: Cell::default() };

    let mut v = vec![&a, &b, &c];

    v.sort_by(|a, b| a.get_value().cmp(&b.get_value()));
}