使用Result在控制流中产生副作用的推荐方法是什么?

时间:2019-04-07 15:53:51

标签: rust control-flow

Result::and_then()非常适合组成控制流。

fn some_fn() -> Result<String, Error> {
    Ok("Yay".to_string())
}
some_fn()
    .and_then(|value| some_other_fn())
    .and_then(|some_other_value| /* ... */)

有时我们想要创建一个副作用,并且仍然传播所发出的值。假设我们要在收到值后立即打印该值:

some_fn()
    .and_then(|value| {
        println!("{}", &value);
        some_other_fn()
    })
    .and_then(|some_other_value| /* ... */)

有更好的方法吗?像Reactive Extensions' tap() operator这样的东西会很棒。

1 个答案:

答案 0 :(得分:2)

mapand_then适用于要转换值的情况。使用matchif let适用于副作用:

let r = some_fn();

if let Ok(v) = &r {
    println!("{}", v);
}

r.and_then(|_| some_other_fn())

另请参阅:

假设,您仅关心ResultOk时的副作用...

您还可以创建一个扩展特征,以将所需的方法添加到Result中。我主张将其命名为inspect,因为它就是the parallel method on Iterator的名称。

trait InspectExt<T> {
    fn inspect<F>(self, f: F) -> Self
    where
        F: FnOnce(&T);
}

impl<T, E> InspectExt<T> for Result<T, E> {
    fn inspect<F>(self, f: F) -> Self
    where
        F: FnOnce(&T),
    {
        if let Ok(v) = &self {
            f(v)
        }
        self
    }
}
some_fn()
    .inspect(|v| println!("{}", v))
    .and_then(|_| some_fn())

另请参阅: