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| /* ... */)
Есть лучший способ сделать это? Что-то вроде Оператор tap()
реактивных расширений было бы здорово.
Это именно то, что я имею в виду. Ничего плохого в том, что у меня есть. Я просто держу глаза и уши открытыми для более элегантных решений (если это возможно). Ваш ответ, как всегда, имеет смысл - Спасибо!
побочный эффект никогда не бывает элегантным
map
и and_then
подходят, когда вы хотите преобразовать значение. Использование match
или if let
подходит для побочных эффектов:
let r = some_fn();
if let Ok(v) = &r {
println!("{}", v);
}
r.and_then(|_| some_other_fn())
Смотрите также:
Предполагая, что вы заботитесь о побочных эффектах только тогда, когда Result
есть Ok
...
Вы также можете создать признак расширения, чтобы добавить нужный метод в Result
. Я бы посоветовал назвать его inspect
, так как это имя параллельный метод на 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())
Смотрите также:
some_other_function
? Если да, то что не так с тем, что у вас есть?