首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何让Result<T、E1>与Result<T、E2>保持一致?

如何让Result<T、E1>与Result<T、E2>保持一致?
EN

Stack Overflow用户
提问于 2015-03-13 07:06:22
回答 1查看 240关注 0票数 4

我有这个代码

代码语言:javascript
复制
fn get_last_commit () -> String {

    Command::new("git")
            .arg("rev-parse")
            .arg("HEAD")
            .output()
            .map(|output| {
                String::from_utf8(output.stdout).ok().expect("error reading into string")
            })
            .ok().expect("error invoking git rev-parse")
}

我希望能够将ok().expect(..)减少一点,这样我就有了理想的东西:

代码语言:javascript
复制
fn get_last_commit () -> String {

    Command::new("git")
            .arg("rev-parse")
            .arg("HEAD")
            .output()
            .and_then(|output| {
                String::from_utf8(output.stdout)
            })
            .ok().expect("error invoking git rev-parse")
}

然而,这不起作用,因为错误没有对齐,留给我的是:

代码语言:javascript
复制
    mismatched types:
     expected `core::result::Result<_, std::io::error::Error>`,
        found `core::result::Result<collections::string::String, collections::string::FromUtf8Error>`
    (expected struct `std::io::error::Error`,
        found struct `collections::string::FromUtf8Error`)

我知道错误处理在上个月发生了很大的变化,我有一种感觉,应该在没有太多麻烦的情况下让它们对齐。我似乎无法弄清楚这一点。

EN

回答 1

Stack Overflow用户

发布于 2015-03-13 07:35:04

问题是传递给and_then的闭包需要返回一个与调用and_thenResult具有相同错误类型的Result;否则,and_then不能返回任何单一类型;and_then将一种Ok类型映射到另一种类型,但保持错误类型不变。

由于您只是通过将错误值转换为带有ok()的选项来丢弃错误值,因此可以在调用and_then之前和在闭包内执行此操作,因为and_thenOption上返回的Option类型仅取决于闭包返回的值:

代码语言:javascript
复制
fn get_last_commit () -> String {

    Command::new("git")
            .arg("rev-parse")
            .arg("HEAD")
            .output()
            .ok()
            .and_then(|output| {
                String::from_utf8(output.stdout).ok()
            })
            .expect("error invoking git rev-parse")
}

如果您真正关心error值,则需要定义自己的error类型,该类型可以包含这两种类型的错误中的任何一种,并包装这两种错误中的任何一种。FromError特征和try!宏提供了一种方便的方法来包装值并从函数中的几个位置之一返回它,尽管在本例中map_err可能是更好的方法,因为您是通过链接的方法调用而不是单独的语句来完成这项工作的。

代码语言:javascript
复制
enum MyError {
    Io(IoError),
    Utf8(FromUtf8Error)
}

fn get_last_commit () -> Result<String,MyError> {

    Command::new("git")
            .arg("rev-parse")
            .arg("HEAD")
            .output()
            .map_err(MyError::Io)
            .and_then(|output| {
                String::from_utf8(output.stdout)
                       .map_err(MyError::Utf8)
            })
}

如果您注意到了,这与前面的解决方案非常相似,强制将两个结果类型合并为一个公共类型;在第一个解决方案中,它只是通过使用ok()丢弃错误值,而在第二个解决方案中,它保留错误值以便您可以返回它,但是现在您需要一个可以包装这两种类型的额外机制。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29022016

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档