gpt4 book ai didi

rust - 使用 `Cell` 和 `RefCell` 进行内存或延迟评估的惯用方法

转载 作者:行者123 更新时间:2023-11-29 08:27:17 38 4
gpt4 key购买 nike

下面的代码有效。它延迟计算 xys 并缓存到 Foo::x: Cell, Foo::ys: RefCell分别。

但是,我觉得可能有更好的方法来做到这一点。我不喜欢我必须制作一个包装器 CacheVecGuard 以便在调用站点上我可以使用 self.borrow_ys() 而不是冗长的 &self.ys.borrow( ).1.

如何改进这段代码?

在这种情况下是否有任何规范的片段可以进行惰性评估或内存? (我知道 lazy_static 不适合)

use std::cell::{RefCell, Cell, Ref};
use std::ops::Deref;

struct CacheVecGuard<'a>(Ref<'a, (bool, Vec<f64>)>);

impl<'a> Deref for CacheVecGuard<'a> {
type Target = [f64];

fn deref(&self) -> &Self::Target {
&(self.0).1
}
}

fn pre_calculate_x(x: f64) -> f64 {
x
}

fn pre_calculate_ys(x: f64, ys: &mut [f64]) {
for i in 0..ys.len() {
ys[i] += 1.0;
}
}

struct Foo {
pub a: f64,
x: Cell<Option<f64>>,
ys: RefCell<(bool, Vec<f64>)>,
}

impl Foo {
pub fn new(a: f64) -> Self {
Self {
a,
x: Cell::new(None),
ys: RefCell::new((false, vec![0.0; 10])),
}
}

fn get_x(&self) -> f64 {
match self.x.get() {
None => {
let x = pre_calculate_x(self.a);
self.x.set(Some(x));
println!("Set x to {}", x);
x
}
Some(x) => x,
}
}

fn borrow_ys(&self) -> CacheVecGuard {
{
let (ref mut ready, ref mut ys) = *self.ys.borrow_mut();
if !*ready {
pre_calculate_ys(self.a, ys);
println!("Set ys to {:?}", ys);
*ready = true;
}
}
CacheVecGuard(self.ys.borrow())
}

fn clear_cache(&mut self) {
*(&mut self.ys.borrow_mut().0) = false;
self.x.set(None);
}

pub fn test(&self) -> f64 {
self.borrow_ys()[0] + self.get_x()
}

pub fn set_a(&mut self, a: f64) {
self.a = a;
self.clear_cache();
}
}

fn main() {
let mut foo = Foo::new(1.0);
println!("{}", foo.test());
foo.set_a(3.0);
println!("{}", foo.test());
}

打印

Set ys to [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
Set x to 1
2
Set ys to [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
Set x to 3
5

Playground

最佳答案

您需要清除缓存的能力这一事实意味着您必须有一个守卫。否则,对 set_a 的调用可能会使 borrow_ys 之前返回的裸引用无效。编译器可以验证这不会发生的唯一方法是返回一个守卫并从守卫借用。

如果您可以取消清除缓存的功能,您可以使用 lazycell 中的 LazyCell 类型而不是 crate 。

关于rust - 使用 `Cell` 和 `RefCell` 进行内存或延迟评估的惯用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44574028/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com