Упрощение сопоставления ржавчины с помощью комбинаторов - PullRequest
0 голосов
/ 18 марта 2020

У меня есть что-то вроде этого:

match fnX(
    fnY(x), // Returns Result<(), X>
) // Returns Result<(), Y>
.await
{
    Ok(v) => {
        if v.is_err() {
            error!("error = {}", v);
        }
    }
    Err(e) => error!("error = {}", e),
};

Как я могу написать это с помощью комбинаторов, чтобы мне нужно было error! только один раз? Я не хочу ничего делать со значением Ok, просто выведите ошибку, будь то fnX или fnY.

Ответы [ 2 ]

3 голосов
/ 18 марта 2020

Я предполагаю, что вы хотели упростить что-то вроде этого (удалив .await, который не связан с проблемой):

match fnX(x) { // Returns Result<X, EX>
    Ok(y) => match fnY(y) { // Returns Result<Y, EY>
        Ok(_) => println!("Success!"),
        Err(e) => error!("error = {}", e),
    },
    Err(e) => error!("error = {}", e),
}

Если типы ошибок одинаковы, вы можете упростить код с and_then:

match fnX(x).and_then(fnY) {
    Ok(_) => println!("Success!"),
    Err(e) => error!("error = {}", e),
}

Если типы ошибок отличаются, вы можете использовать map_err, чтобы преобразовать их в один тип:

match fnX(x)
    .map_err(MyError::from)
    .and_then(|y| fnY(y).map_err(MyError::from))
{
    Ok(_) => println!("Success!"),
    Err(e) => error!("error = {}", e),
}

Последнее можно упростить с помощью последней версии для разработки map_for ящик:

match map_for!(y <- fnX (x);
               v <- fnY (y);
               => v)
{
    Ok(_) => println!("Success"),
    Err(e @ MyError { .. }) => error!("error = {}", e),
}
  • Обратите внимание, что аннотация @ MyError {..} требуется только в том случае, если компилятор не может автоматически определить тип ошибки.
  • Полный отказ от ответственности: я являюсь автором map_for ящика.
2 голосов
/ 18 марта 2020

Вам не нужен такой «комбинатор».

fnX принимает аргумент типа Result<(), X> и возвращает Result<(), Y>

Когда код свернут, он может помогите отделить выражения, сделав их более читабельными.

let result = fnY(x);
match fnX(result).await {
    Ok(v) => {
        // here v is ok value, in this case ()
    }
    Err(e) => error!("error = {}", e),
};
...