【问题标题】:Rust mutable container of immutable elements?Rust 不可变元素的可变容器?
【发布时间】:2022-10-23 04:21:45
【问题描述】:

使用 Rust,通常是否有可能拥有一个包含不可变值的可变容器?

例子:

struct TestStruct { value: i32 }

fn test_fn()
{
    let immutable_instance = TestStruct{value: 123};
    let immutable_box = Box::new(immutable_instance);
    let mut mutable_vector = vec!(immutable_box);

    mutable_vector[0].value = 456;
}

在这里,我的TestStruct 实例被包装在两个容器中:一个Box,然后是一个Vec。从新 Rust 用户的角度来看,将 Box 移动到 Vec 使 BoxTestStruct 实例都可变是令人惊讶的。

是否有类似的构造,其中装箱的值是不可变的,但盒子的容器是可变的?更一般地说,是否有可能拥有多个“层”容器而整个树不可变或不可变?

【问题讨论】:

  • 您可以将Box::new() 更改为Rc::new() 并更接近您想要的。 Rc 是一个共享容器,它可以防止其内容发生变化。 (但即便如此,如果只有一个所有者,也有办法做到这一点......)
  • Rust 中的可变性不是值的函数,而是绑定的函数。您可以获取一个“不可变”值并使其再次可变,只需将其分配给mut 变量:playground

标签: rust containers immutability


【解决方案1】:

是否有类似的构造,其中装箱的值是不可变的,但盒子的容器是可变的?更一般地说,是否有可能拥有多个“层”容器而整个树不可变或不可变?

并不真地。您可以轻松地创建一个(只需创建一个实现 Deref 而不是 DerefMut 的包装器对象),但现实情况是 Rust 并没有真正看到(im)可变性,因为它主要关注的是控制共享/可见性.

毕竟,对于外部观察者来说,两者之间有什么区别

mutable_vector[0].value = 456;

mutable_vector[0] = Box::new(TestStruct{value: 456});

?

没有答案,因为 Rust 的所有权系统意味着观察者不可能保留原始 TestStruct 的句柄,因此他们无法知道该结构是否被替换或修改到位[1][2].

如果您想保护您的内部状态,请改用可见性:https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8a9346072b32cedcf2fccc0eeb9f55c5

mod foo {
    pub struct TestStruct { value: i32 }
    impl TestStruct {
        pub fn new(value: i32) -> Self { Self { value } }
    }
}

fn test_fn() {
    let immutable_instance = foo::TestStruct{value: 123};
    let immutable_box = Box::new(immutable_instance);
    let mut mutable_vector = vec!(immutable_box);

    mutable_vector[0].value = 456;
}

无法编译,因为从test_fn 的角度来看,TestStruct::value 是不可访问的。因此test_fn 无法改变TestStruct,除非您在其上添加&mut 方法。


[1]:从技术上讲,他们可以检查内存中的地址,并且可能告诉他们,但即便如此,这也不是一件确定的事情(在任何一个方向上),因此 pinning 是一件事情。

[2]:这种可观察性的区别也被其他语言所接受,例如Clojure 语言在很大程度上属于“所有事物不可变”的一面,但是它有一个概念瞬变这允许locally mutable objects

【讨论】:

    猜你喜欢
    • 2023-01-09
    • 2012-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-18
    相关资源
    最近更新 更多