Как идиоматически конвертировать из Option <T>в Result ? - PullRequest
2 голосов
/ 19 апреля 2020

Я новичок в Rust ie! Как лучше всего конвертировать из Option<T> в Result<T, ()>?

Черта TryFrom кажется распространенной и возвращает результат. Популярный num_traits ' NumCast имеет много конверсий, но все они возвращают Option<T>. Точно так же, как и конструкторы NonZero *, такие как NonZeroI32 в стандартной библиотеке Rust . Затем я заметил, что NumCast реализует from(), который возвращает Option<T>, поэтому я подумал, что, возможно, у него был нестандартный способ работы в целом, но затем я увидел реализации NonZero * и поставил под сомнение эту идею.

Несмотря на это, переход от параметров к результатам кажется частым, и я пока не нашел изящного способа сделать это. Например:

/// Add common conversion from an i32 to a non-zero i32.
impl TryFrom<Container<i32>> for Container<NonZeroI32> {
  type Error = ();
  fn try_from(container: Container<i32>) -> Result<Self, ()> {
    // NonZeroI32::new() returns an Option not a Result. Try a helper.
    Ok(Self(option_to_result(NonZeroI32::new(container.0))?))
  }
}

/// Helper function to convert from an Option to a Result (both types are
/// foreign and so is From).
fn option_to_result<T>(option: Option<T>) -> Result<T, ()> {
  if let Some(some) = option {
    Ok(some)
  } else {
    Err(())
  }
}
/// Add another common conversion from an i32 to an i16.
impl TryFrom<Container<i32>> for Container<i16> {
  type Error = ();
  fn try_from(container: Container<i32>) -> Result<Self, ()> {
    // NumCast::from() also returns an Option not a Result. Try map_or() instead
    // of the helper.
    Ok(Self(NumCast::from(container.0).map_or(Err(()), |x| Ok(x))?))
  }
}

(Выше приведены примеры на Rust Playground .)

Эти преобразования NumCast, NonZero * и TryFrom кажутся достаточно распространенными, но мой подход кажется неуклюжим, как будто я сравниваю типы Option и Result друг с другом. Я борюсь с этими преобразованиями, а также упускаю фундаментальную точку типа Option, заданную Result<T,()>, ощущается похожим.

Итак, каков идиоматический c способ преобразования Option<T> в Result<T,()> в Ржавчина 2018 года?

1 Ответ

6 голосов
/ 19 апреля 2020

Option имеет метод ok_or, пригодный именно для этого (ну, на самом деле, для более широкого случая, но ваш запрос тоже подходит):

fn option_to_result<T>(option: Option<T>) -> Result<T, ()> {
  option.ok_or(())
}

Модифицированная детская площадка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...