Rust 在单个表达式中创建、初始化和运行的惯用方法
有时你会遇到这样的情况:Rust 在单个表达式中创建、初始化和运行的惯用方法,rust,Rust,有时你会遇到这样的情况: let mut something = Something::new(); something.set_property_a("foo"); something.set_property_b("bar"); let result = something.result(); 您所需要的只是结果,但现在范围被某些东西污染了 在Kotlin中,您可以这样做(在其他版本中,但为了清晰起见,请使用详细版本): T.let(closure)只运行closure,将调用它的对象(S
let mut something = Something::new();
something.set_property_a("foo");
something.set_property_b("bar");
let result = something.result();
您所需要的只是结果,但现在范围被某些东西污染了
在Kotlin中,您可以这样做(在其他版本中,但为了清晰起见,请使用详细版本):
T.let(closure)
只运行closure,将调用它的对象(Something
的实例)作为参数,并返回闭包返回的任何内容。非常轻巧和简单的概念,但非常有用
在铁锈中可以做类似的事情吗?我想到的最接近的方法是:
let result = {
let mut x = Something::new();
x.set_property_a("foo");
x.set_property_b("boo");
x.result()
};
您可以使用。这是Rust中实现您想要的目标的惯用方法:
#[derive(Debug)]
struct Something {
property_a: String,
property_b: String,
}
#[derive(Debug, Default)]
struct SomethingBuilder {
property_a: Option<String>,
property_b: String,
}
#[derive(Debug)]
enum BuildError {
ANotSet,
}
impl SomethingBuilder {
fn new() -> Self {
Self::default()
}
fn with_a(mut self, a: String) -> Self {
self.property_a = Some(a);
self
}
fn with_b(mut self, b: String) -> Self {
self.property_b = b;
self
}
fn build(self) -> Result<Something, BuildError> {
Ok(Something {
property_a: self.property_a.ok_or(BuildError::ANotSet)?,
property_b: self.property_b,
})
}
}
fn main() {
let thing = SomethingBuilder::new()
.with_a("foo".into())
.with_b("bar".into())
.build() // returns BuildError if set_a is left out
.unwrap();
println!("{:?}", thing);
}
#[派生(调试)]
构造某物{
属性a:字符串,
属性_b:String,
}
#[派生(调试,默认)]
结构构建器{
房地产:期权,
属性_b:String,
}
#[导出(调试)]
枚举生成错误{
阿诺塞特,
}
安装一些东西{
fn new()->Self{
Self::default()
}
fn带_a(mut self,a:String)->self{
self.property_a=Some(a);
自己
}
fn带_b(mut self,b:String)->self{
self.property_b=b;
自己
}
fn构建(自)->结果{
好的{
属性a:self.property\u a.ok\u或(BuildError::ANotSet)?,
property_b:self.property_b,
})
}
}
fn main(){
let thing=SomethingBuilder::new()
.with_a(“foo.into())
.with_b(“bar.into())
.build()//如果忽略了集合a,则返回BuildError
.unwrap();
println!(“{:?}”,东西);
}
例如,见
在builder结构中,当调用
build
方法时,可以执行所有需要的验证。如果一切正常,您可以返回新构建的struct
。此模式的优点是代码的可读性(无“污染”)和为用户保证构建的struct
完全有效。在这两种情况下,x
不会泄漏到外部范围。你还想要什么?你的例子就是我认为的习惯用法。但是,我通常会继续将其提取到函数中。@JoshLee我不知道或不确认这是正确的方法,这似乎是,谢谢。旁注:为了完整性,我建议提供一个生成器作为API的一部分,但是如果在我的程序中我只“需要”一次或两次生成器,我只会使用块表达式。@MatthieuM。当然,对于一到两次的使用来说(大约30行,而不是4行),这是一种过度使用
#[derive(Debug)]
struct Something {
property_a: String,
property_b: String,
}
#[derive(Debug, Default)]
struct SomethingBuilder {
property_a: Option<String>,
property_b: String,
}
#[derive(Debug)]
enum BuildError {
ANotSet,
}
impl SomethingBuilder {
fn new() -> Self {
Self::default()
}
fn with_a(mut self, a: String) -> Self {
self.property_a = Some(a);
self
}
fn with_b(mut self, b: String) -> Self {
self.property_b = b;
self
}
fn build(self) -> Result<Something, BuildError> {
Ok(Something {
property_a: self.property_a.ok_or(BuildError::ANotSet)?,
property_b: self.property_b,
})
}
}
fn main() {
let thing = SomethingBuilder::new()
.with_a("foo".into())
.with_b("bar".into())
.build() // returns BuildError if set_a is left out
.unwrap();
println!("{:?}", thing);
}