使用 Result 在控制流中产生副作用的推荐方法是什么?
What's the recommended way to produce side effects in control flow using Result?
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 这样的东西会很棒。
map
和 and_then
适用于需要转换值的情况。使用 match
或 if let
适用于副作用:
let r = some_fn();
if let Ok(v) = &r {
println!("{}", v);
}
r.and_then(|_| some_other_fn())
另请参阅:
- Why does Rust need the `if let` syntax?
假设您只关心 Result
是 Ok
时的副作用...
您还可以创建一个 扩展特征 以将所需的方法添加到 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())
另请参阅:
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 这样的东西会很棒。
map
和 and_then
适用于需要转换值的情况。使用 match
或 if let
适用于副作用:
let r = some_fn();
if let Ok(v) = &r {
println!("{}", v);
}
r.and_then(|_| some_other_fn())
另请参阅:
- Why does Rust need the `if let` syntax?
假设您只关心 Result
是 Ok
时的副作用...
您还可以创建一个 扩展特征 以将所需的方法添加到 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())
另请参阅: