rust - 在单个表达式中创建、初始化和运行的惯用方式

标签 rust

有时候你会遇到这样的事情:

let mut something = Something::new();
something.set_property_a("foo");
something.set_property_b("bar");
let result = something.result();

您所需要的只是结果,但现在作用域被某些东西污染了。

在 Kotlin 中,您可以这样做(在其他版本中,但为了清楚起见使用冗长的版本):

val result = Something().let { x ->
    x.propertyA = "foo"
    x.propertyB = "bar"
    x.result()
}

T.let(closure) 只是运行闭包,将调用它的对象(Something 的实例)作为参数并返回闭包返回的任何内容。极其轻巧和简单的概念,但非常有帮助。

在 Rust 中可以做类似的事情吗?我想出的最接近的是:

let result = {
    let mut x = Something::new();
    x.set_property_a("foo");
    x.set_property_b("boo");
    x.result()
};

最佳答案

您可以使用 builder pattern .这是 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);
}

参见 this real world usage例如。

在构建器结构中,您可以在调用 build 方法时进行所有您想要的验证。如果一切正常,就可以返回新建的struct。这种模式的优点是代码的可读性(无“污染”)为用户保证构建的struct 是完全有效的。

关于rust - 在单个表达式中创建、初始化和运行的惯用方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47822002/

相关文章:

rust - 如何在 Rust 的内置函数上实现特征?

compilation - 有 Rust 解释器吗?

rust - 借用带有字段的可变结构

string - 将字符串与从输入读取的字符串进行比较在 Rust 中不匹配

iterator - 如何使用生命周期嵌套可变访问?

arrays - 沿维度求和数组

types - Rust 有 C 的 typedef 的等价物吗?

io - 使用 Read::read_to_string 从 TcpStream 读取会挂起,直到连接被远程端关闭

rust - 有没有办法在 Option 中拆分变量而不必使用 if 语句?

windows - ReadConsoleInputW 包装器和所有权