接受 Result<T, E> 作为函数参数是惯用的 Rust 吗?
Posted
技术标签:
【中文标题】接受 Result<T, E> 作为函数参数是惯用的 Rust 吗?【英文标题】:Is it idiomatic Rust to accept a Result<T, E> as a function argument? 【发布时间】:2020-10-08 06:27:22 【问题描述】:考虑以下代码:
fn foo(x: i32) -> Result<i32, Error>
//...
fn bar(x: Result<i32,Error>) -> Result<i32, Error>
//...
fn main()
let y = bar(foo(2)).unwrap();
传递Result
类型是惯用的吗?或者您应该在直接传递i32
之前处理错误或解开bar()
的结果。
【问题讨论】:
【参考方案1】:接受Result
作为参数是很不寻常的,除非在用于处理Result
s 的通用库中。
Result
具有a lot of methods,这有助于使其更符合人体工程学。例如,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();
【讨论】:
【参考方案2】:我不能说我见过的情况很有意义,但如果没有更清楚地解释你为什么要这样做,就很难提供更多帮助。
本质上,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
没有实际用途,那么不,这不是惯用的,输入是不必要且无用的复杂。
在这种情况下,您想要的是:
fn bar(x: i32) -> Result<i32, Error>
//...
fn main()
let y = foo(2).and_then(bar).unwrap();
【讨论】:
以上是关于接受 Result<T, E> 作为函数参数是惯用的 Rust 吗?的主要内容,如果未能解决你的问题,请参考以下文章
设计一个函数,它接受不定数量的参数,这是参数都是函数。这些函数都接受一个回调函数作为参数,按照回调函数被调用的顺序返回函数名
await Task<T> 和 Task<T>.Result 有啥区别?
Rust Diesel 原始 SQL 给出错误“`std::result::Result<Vec<T>,diesel::result::Error>` 所需的类型注释”
使用Spring Data JPA查询时,报result returns more than one elements异常