Это идиоматия c Rust принять результат как аргумент функции? - PullRequest
2 голосов
/ 18 июня 2020

Рассмотрим следующий код:

fn foo(x: i32) -> Result<i32, Error> {
    //...
}

fn bar(x: Result<i32,Error>) -> Result<i32, Error> {
    //...
}

fn main() {
    let y = bar(foo(2)).unwrap();
}

Это идиоматия c, чтобы передать тип Result? Или вы должны обработать ошибку или развернуть результат bar() перед непосредственной передачей i32.

Ответы [ 2 ]

6 голосов
/ 18 июня 2020

Довольно необычно принимать Result в качестве аргумента, за исключением библиотек общего назначения для работы с Result s.

Result имеет множество методов , которые помогите сделать работу с ним более эргономичной c. Например, and_then, который связывает вызов функции с предыдущим результатом. Ваш пример можно изменить на:

fn foo(x: i32) -> Result<i32, Error> {
    //...
}

fn bar(x: i32) -> Result<i32, Error> {
    //...
}

fn main() {
    let y = foo(2).and_then(|value| bar(value)).unwrap();

    // or more concisely in this simple case:
    let y = foo(2).and_then(bar).unwrap();
}
3 голосов
/ 18 июня 2020

Не могу сказать, что видел ситуацию, в которой это имело смысл, но без более четкого объяснения того, почему вы это сделаете, трудно помочь больше.

По сути, имеет bar есть ли какое-либо использование для ввода Err(), или он просто будет передавать его напрямую? В первом случае, тогда да, для bar может иметь смысл взять Result - хотя, учитывая, что вы задаете вопрос, который выглядит маловероятным

Однако, если bar начинается с чего-то в строки

fn bar(x: Result<i32, Error>) -> Result<i32, Error> {
    let y = x?;
    // work with an actual `i32` and potentially output an error as well

, то есть он не имеет фактического использования для Err, тогда нет, это не идиоматия c, ввод излишне и бесполезно сложен.

В этом если вам нужно:

fn bar(x: i32) -> Result<i32, Error> {
    //...
}

fn main() {
    let y = foo(2).and_then(bar).unwrap();
}
...