Rust 如何用易出错的初始值设定项惰性地初始化/填充“Option”?

Rust 如何用易出错的初始值设定项惰性地初始化/填充“Option”?,rust,optional,lazy-initialization,Rust,Optional,Lazy Initialization,假设我有一个包含选项的结构,其中资源是我需要使用的某种类型,需要分配外部资源(在实际情况中是GPU内存),因此可能会失败。在方法中,如果尚未完成分配,我希望尝试分配,但如果分配失败,则传播或处理错误 如果不是因为这个失败的案例,这将是完美的。事实上,我想到的最整洁的解决方案是一个展开(),这是不雅观的,因为它看起来像一个潜在的恐慌: struct容器{ 资源:选择, ... } impl容器{ ... fn激活(&mut self)->结果{ 如果self.resource.is_none(){

假设我有一个包含
选项
的结构,其中
资源
是我需要使用的某种类型,需要分配外部资源(在实际情况中是GPU内存),因此可能会失败。在方法中,如果尚未完成分配,我希望尝试分配,但如果分配失败,则传播或处理错误

如果不是因为这个失败的案例,这将是完美的。事实上,我想到的最整洁的解决方案是一个
展开()
,这是不雅观的,因为它看起来像一个潜在的恐慌:

struct容器{
资源:选择,
...
}
impl容器{
...
fn激活(&mut self)->结果{
如果self.resource.is_none(){
self.resource=Some(resource::new()?);
}
让resource:&mut resource=self.resource.as_mut().unwrap();
//…现在使用“资源”进行操作。。。
好(())
}
...
}
有没有一种方法可以初始化
选项
,而不那么麻烦?要明确的是,我不仅要避免
unwrap()
,而且还要避免总体可读性。如果另一种选择更加复杂和间接,我宁愿坚持这一点


完整的示例代码():

#[派生(调试)]
结构资源{}
#[导出(调试)]
结构错误;
impl资源{
fn new()->结果{
Ok(资源{})
}
fn写入(&mut self){}
}
#[导出(调试)]
结构容器{
资源:选择,
}
impl容器{
fn new()->Self{
自我{资源:无}
}
fn激活(&mut self)->结果{
如果self.resource.is_none(){
self.resource=Some(resource::new()?);
}
self.resource.as_mut().unwrap().write();
好(())
}
}
fn main(){
容器::new().activate();
}
确实如此,但返回
结果是简化代码的方法。但是,正如您已经发现的,没有例如
try\u get\u或\u insert\u with()
方法

其他解决办法也同样冗长。但是,您可以使用
匹配
,为避免类似情况:

fn激活(&mut self)->结果{
让res=match&mut self.resource{
一些(res)=>res,
None=>self.resource.get_或_insert(resource::new()?),
};
res.write();
好(())
}
如果经常使用此方法,那么您还可以定义自己的
try\u get\u或\u insert\u with()
trait方法,并为实现它

trait TryGetOrInsert{
fn使用(&mut self,f:f)->结果尝试获取或插入
哪里
F:FnOnce()->结果;
}
选项的impl TryGetOrInsert{
fn使用(&mut self,f:f)->结果尝试获取或插入
哪里
F:FnOnce()->结果,
{
匹配自我{
一些(值)=>Ok(值),
None=>Ok(self.get_或_insert(f()?),
}
}
}
现在,您可以将
activate()
方法简化为以下内容:

fn激活(&mut self)->结果{
让res=self.resource。尝试使用(| | resource::new())获取或插入?;
res.write();
好(())
}

在用例多次出现之前,我不会添加这么多代码,但我喜欢使用
self.get\u或\u insert(value)
处理移动和借用的技巧@KevinReid我更新了答案,使用
匹配
获取或插入