我有这个代码
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(..)减少一点,这样我就有了理想的东西:
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")
}然而,这不起作用,因为错误没有对齐,留给我的是:
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`)我知道错误处理在上个月发生了很大的变化,我有一种感觉,应该在没有太多麻烦的情况下让它们对齐。我似乎无法弄清楚这一点。
发布于 2015-03-13 07:35:04
问题是传递给and_then的闭包需要返回一个与调用and_then的Result具有相同错误类型的Result;否则,and_then不能返回任何单一类型;and_then将一种Ok类型映射到另一种类型,但保持错误类型不变。
由于您只是通过将错误值转换为带有ok()的选项来丢弃错误值,因此可以在调用and_then之前和在闭包内执行此操作,因为and_then在Option上返回的Option类型仅取决于闭包返回的值:
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可能是更好的方法,因为您是通过链接的方法调用而不是单独的语句来完成这项工作的。
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()丢弃错误值,而在第二个解决方案中,它保留错误值以便您可以返回它,但是现在您需要一个可以包装这两种类型的额外机制。
https://stackoverflow.com/questions/29022016
复制相似问题