I have this code
fn get_last_commit () -> String {
Command::new(\"git\")
.arg(\"rev-parse\")
.arg(\"HEAD\")
.outp
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.
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")
}
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)
})
}
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.