问题标签 [interior-mutability]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
0 回答
54 浏览

tree - 我应该使用 RefCell> 或 Rc> 对于具有可以突变的父母的树?

我想parent使用 Rust 实现一个节点具有字段的树。从官方指南添加-a-reference-from-a-child-to-its-parent,他们使用结构

要使用可变的实例RefCell<Rc<T>>,我可以调用.borrow_mut().

在 的文档中std::celllet shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new()));用于将可变性引入Rc.

如果我想要一棵可以变异的父母树,推荐哪棵?

0 投票
1 回答
281 浏览

rust - 比较 RefCell 中包含的值

我有一个字段定义如下的结构:

我在球场上进行了各种borrow_mut()呼叫push_str(.)。最后,我正在使用以下方法评估其价值:

尽管如此,断言行会引发编译时错误,并显示以下消息:

错误[E0369]:二进制运算==不能应用于类型std::cell::Ref<'_, std::string::String>

我理解为什么会发生错误,因为编译器甚至提示:

的实现std::cmp::PartialEq可能会丢失std::cell::Ref<'_, std::string::String>

我的问题是:我应该如何比较 a 中包含的值RefCell<T>(通常在这种情况下,将包含的字符串与预期值进行比较)。

谢谢 !

0 投票
1 回答
405 浏览

rust - 如何通过 Rc> 到想要 &dyn T 的 fn?

我无法将参数传递给 fn。

编译器告诉我:

我认为这就像rust book中的示例Rc一样,其中自动取消引用并从我可以调用的 RefCell 中获取值borrow()

我也尝试过显式取消引用,但似乎没有任何效果。

如何调用foo()中的每个dyn T对象self

0 投票
1 回答
46 浏览

data-structures - 有RCs 在一个模块和 Rc>s 在另一个引用相同的数据

我有一个这样的数据结构:

我显然不需要该模块中节点的可变性。我这里也没有循环引用。

但我有另一个模块,其中包含节点,我需要可变性:

我只是想不出一种方法来Rc<Node>为节点本身创建 s 以及Rc<RefCell<Node>>Network.

您对如何在nodes模块中可变节点旁边的模块中实现不变性有任何想法network吗?

Node或者除了将结构内的前任节点的引用声明为 之外没有其他方法Rc<RefCell<Node>>,即使我在这里不需要可变性(我想避免这种情况)?

0 投票
0 回答
343 浏览

rust - 一个RefCell的元素可以吗> 存储在结构中修改同一 Vec 中另一个元素的值?

我有一个包含向量的结构,其元素必须能够修改向量中的其他元素。

我试着这样做:

操场

但是,我收到了这些错误

我该怎么做?另请注意,由于某些限制,我不想在主函数中创建任何额外的变量。

攻击功能就像我应该运行的主程序中 vec 的不同元素的更新功能一样

0 投票
1 回答
480 浏览

rust - 为什么我的 RefCell 的零成本替代方案不是实现内部可变性的标准方法?

我一直在思考为什么在大多数情况下 Rust 的内部可变性需要运行时检查(例如RefCell)。看起来我找到了一个没有运行时成本的安全替代方案。我已经调用了该类型SafeCell(主要是因为它是一个安全的包装器UnsafeCell),它允许您将任何函数应用于包装的值,而不会有引用转义的风险:

这种类型可用于内部可变性,如下所示:

或结合Rc

操场

  1. 这种类型是否存在任何安全/健全性问题?
  2. 如果不是,为什么这样的类型不是实现内部可变性的标准方法?看起来它与RefCell提供静态生命周期检查而不是运行时检查一样有用。
0 投票
2 回答
409 浏览

rust - 如何读取和修改链接树中节点的值?

我正在努力在 Rust 中实现树结构。特别是获取和修改节点的值。使用价值的惯用方式是什么?

注意:实现是给定的,不能更改。

0 投票
1 回答
1149 浏览

rust - API 设计中的内部可变性滥用?

我在 C++ 方面的背景让我对内部可变性感到不舒服。下面的代码是我围绕这个主题的调查。

我同意,从借用检查器的角度来看,处理每个结构上的许多引用,这些引用可能很快或稍后会改变内部状态;这显然是内部可变性可以提供帮助的地方。

此外,在The Rust Programming Language的第15.5 章“RefCell 和内部可变性模式”中,关于trait 及其在 struct 上的实现的示例让我认为它是一种常见的 API 设计,系统地优先考虑,即使它很明显某种可变性迟早会成为强制性的。发送消息时如何不改变其内部状态的实现?例外只是打印消息,这与 一致,但一般情况可能包括写入某种内部流,这可能意味着缓冲、更新错误标志......所有这些当然需要 MessengerMockMessenger&self&mut selfMessenger&self&mut selfimpl Write for File.

在我看来,依靠内部可变性来解决这个问题听起来像是在 C++ 中const_cast滥用或滥用mutable成员,只是因为在应用程序的其他地方我们对 ness 不一致 const(C++ 学习者的常见错误)。

那么,回到下面的示例代码,我应该:

  • 使用&mut self(编译器不会抱怨,即使它不是强制性的) from change_e()tochange_i()以与我更改存储整数的值的事实保持一致?
  • 继续使用&self,因为内部可变性允许它,即使我实际上改变了存储整数的值?

这个决定不仅对结构本身来说是本地的,而且会对使用这个结构在应用程序中表达的内容产生很大的影响。第二种解决方案肯定会有很大帮助,因为只涉及共享引用,但它是否与 Rust 中的预期一致。

我在Rust API Guidelines中找不到这个问题的答案 。是否有任何其他类似于 C++CoreGuidelines的 Rust 文档?

0 投票
2 回答
88 浏览

rust - 待确定的数据:内部可变性还是单独的HashMap?

我有一个struct,叫做它Book,假设它存储了书店出售的一本书上的数据。它需要在某些数据结构(例如 with Rc)中的许多地方引用,因此不能以正常方式可变地借用。但是,它有一些属性,比如它的价格,需要在初始化之后的某个时间填充,在对象已经有未完成的引用之后。

到目前为止,我可以想到两种方法来做到这一点,但它们都有缺点:

  • 内部可变性:给出Book一个字段,例如 price: RefCell<Option<i32>>初始化到RefCell::new(Option::None)何时Book初始化。稍后,当我们确定这本书的价格时,我们可以使用borrow_muttopriceSome(10)代替,然后我们就可以通过borrow它来检索它的价值。

    我的感觉是,一般来说,除非必要,否则人们希望避免内部可变性,而且这里似乎不应该是所有必要的。这种技术也有点尴尬Option,因为我们需要它,因为价格直到以后才会有价值(并且将其设置为0-1同时看起来不像Rust),但这需要在某些地方使用很多matches 或unwraps我们可以在逻辑上确定价格已经被填写。

  • 单独的表:根本不将价格存储在里面Book,而是制作一个单独的数据结构来存储它,例如price_table: HashMap<Rc<Book>, i32>。有一个函数在确定价格时创建并填充此表,然后通过引用(可变或不可变)将其传递给需要了解或更改书籍价格的每个函数。

    像我一样来自 C 背景,HashMap感觉在速度和内存方面都是不必要的开销,因为数据已经有一个自然的位置(内部Book)并且“应该”可以通过简单的指针追踪访问。这个解决方案还意味着我必须用一个引用的附加参数来混淆很多函数price_table

这两种方法中的一种在 Rust 中通常更惯用,还是有其他方法可以避免这种困境?我确实看到了Once,但我认为这不是我想要的,因为我仍然必须在初始化时知道​​如何填写price,而我不知道。

当然,在其他应用程序中,我们可能需要其他类型i32来表示我们想要的属性,所以我希望能够处理一般情况。

0 投票
2 回答
349 浏览

multithreading - Rust:允许多个线程修改图像(向量的包装器)?

假设我有一个包装矢量的“图像”结构:

它可以通过“视图”结构访问,该结构抽象了图像的内部块。假设我只想写入图像 ( set_pixel())。

现在假设我有一个图像,我希望有 2 个线程同时修改它。这里我使用了 rayon 的作用域线程池:

这不起作用,因为

  1. &mut img同时有2个,这是不允许的
  2. “闭包的寿命可能比当前函数长,但它借用v1了当前函数所拥有的 ”

所以我的问题是

  1. 如何修改RawImageView,以便我可以有 2 个线程修改我的图像?
  2. 即使线程是作用域的,为什么它仍然抱怨闭包的生命周期?我该如何克服呢?

游乐场链接

我尝试过的一种方法(并且有效)是modify()创建并返回 a RawImage,然后让线程将其推送到向量中。完成所有线程后,我从该向量构造了完整图像。由于它的 RAM 使用率,我试图避免这种方法。