如何获得结果< T,E1>与结果< T,E2> [英] How to get Result<T, E1> aligned with Result<T,E2>?

查看:112
本文介绍了如何获得结果< T,E1>与结果< T,E2>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个代码

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")
}

'd喜欢能够切割 ok()。expect(..)有点下来,所以我理想地有这样的东西:

I'd like to be able to cut the ok().expect(..) a bit down so that I ideally have something like that:

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")
}

但是,这不工作,因为错误不排队离开我:

However, that doesn't work because the errors don't line up leaving me with:

    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`)

我知道错误处理在最近一个月内发生了很大的变化,我觉得应该有这样的感觉,让他们没有太多的麻烦。

I know the error handling changed quite a bit within the last month and I have the feeling there should be away to get them aligned without too much hassle. I seem unable to figure it out though.

推荐答案

问题是封闭传递给 and_then 需要返回与 Result 相同错误类型的结果 and_then 被调用;否则,没有单一的类型, and_then 可以返回; and_then 将一个 Ok 类型映射到另一个,但保持错误类型相同。

The problem is that the closure passed to the and_then needs to return a Result with the same error type as the Result that and_then was called on; otherwise, there's no single type that and_then could return; and_then maps one Ok type to another, but keeps the error type the same.

由于你只是将错误值转换为 ok()的选项,您可以打开它,然后再调用 and_then ,在关闭中,由和_then Option 类型code>选项仅取决于闭包返回的值:

Since you are just throwing away the error value by converting it to an option with ok() that you unwrap anyhow, you can do that before calling and_then, and within the closure, as the Option type returned by and_then on an Option only depends on the value returned by the closure:

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")
}

如果你真的关心错误值,您需要定义自己的错误类型,其中可能包含两种类型的错误,并将任何错误包装起来。 FromError trait和 try!宏提供了一种方便的方式来包装该值,并从几个在这种情况下,尽管在这种情况下, map_err 可能是一种更好的方法,因为您通过链接方法调用而不是单独的语句来完成此操作。

If you actually cared about the error value, you would need to define your own error type that could contain either of the two types of errors, and wrap either of the errors up. The FromError trait and try! macro offer a convenient way to is wrap up the value and return it from one of several places in your function, though in this case map_err would probably be a better way to do that as you are doing it all via chained method calls rather than separate statements.

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()抛出错误值,而在第二个解决方案中,它保留错误值,以便您可以返回它,但是现在需要可以包装的一种类型的额外机器。

If you notice, this parallels the earlier solution fairly closely, coercing both of the result types into a single common type; in the first solution, it just throws away the error value by using ok(), while in the second, it preserves the error value so you can return it, but you now need the extra machinery of a type that could wrap either.

这篇关于如何获得结果&lt; T,E1&gt;与结果&lt; T,E2&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆