Варианты вариантов и ранний возврат.возвращает ошибку, когда is_none () - PullRequest
1 голос
/ 23 марта 2019

Использование совпадения (как в bar), похоже, является распространенным подходом.

#[derive(Debug)]
pub enum MyErrors {
    SomeError,
}

fn foo(x: Option<u64>) -> Result<u64, MyErrors> {
    if x.is_none() {
      return Err(MyErrors::SomeError);
    } 

    // .. some long code where more options
    // are checked and matched 
    // The ok here is just so the code is simple and compiles
    Ok(x.unwrap() * 2)
}

fn bar(x: Option<u64>) -> Result<u64, MyErrors> {
    match x {
        None => {
            return Err(MyErrors::SomeError)?;
        }
        Some(v) => {
           // .. some long code where more options
           // are checked and matched 
           // The ok here is just so the code is simple and compiles
           Ok(x.unwrap() * 2)
        }
    }
}


fn main() {
    foo(Some(1));
    bar(Some(2));
}

Однако ранние возвраты (например, в foo) значительно уменьшают то, как выглядит вложенный код.Если есть несколько раз, когда параметр должен быть развернут или возвращена ошибка, код наподобие bar становится очень вложенным ...

Какова рекомендуемая практика для раннего возврата ошибки в случае пустых параметров?

1 Ответ

6 голосов
/ 23 марта 2019

Если более длинная цепочка методов нежелательна из-за сложной логики внутри, есть еще несколько читаемых опций с низким отступом.

ok_or и ?

Мы можем преобразоватьот Option до Result с желаемой ошибкой и немедленно разверните его с помощью оператора ?.Это решение, вероятно, обеспечивает наименьший возможный отступ и может быть легко использовано для "разворачивания" нескольких Option с.

fn bar1(x: Option<u64>) -> Result<u64, MyErrors> {
    let x = x.ok_or(MyErrors::SomeError)?;
    // A lot of stuff going on.
    Ok(x * 2)
}

. Это позволит оценить ошибку внутри ok_or независимо от того, будет ли она на самом делеиспользоваться.Если это вычисление дорогое, ok_or_else, который лениво выдает ошибку, будет более эффективным ( связанный вопрос ).

if let

Это решение все еще можетпривести к лестнице кода, если она вложена, но может быть более подходящей, если логика ветвления else более сложна.

fn bar2(x: Option<u64>) -> Result<u64, MyErrors> {
    if let Some(x) = x {
        // Lot of stuff here as well.
        Ok(x * 2)
    } else {
        Err(MyErrors::SomeError)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...