我遇到了一些我不了解Result
,From
,and_then
的内容。
我的impl Parser
中有这个函数,当没有足够的字节时,它会给我一个字节片段或ParseError
:
fn consume_bytes(self: &mut Parser<'a>, len: usize) -> Result<&[u8], ParseError> {
// ...
}
我正在尝试定义另一个函数:
fn read_utf8(self: &mut Parser<'a>, len: usize) -> Result<String, ParseError> {
self.consume_bytes(len)
.and_then(|bytes| String::from_utf8(bytes.to_vec()))
}
无法编译:
error[E0308]: mismatched types
--> src/parser.rs:147:31
|
147 | .and_then(|bytes| String::from_utf8(bytes.to_vec()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `parser::ParseError`, found struct `std::string::FromUtf8Error`
|
= note: expected type `std::result::Result<_, parser::ParseError>`
found type `std::result::Result<std::string::String, std::string::FromUtf8Error>`
因为我已经定义了From
的实现,所以我希望转换能够自动执行,因为通过使用try!
宏,转换是自动的(根据我的理解):< / p>
impl From<FromUtf8Error> for ParseError {
fn from(err: FromUtf8Error) -> ParseError {
ParseError::InvalidConstantPoolEntry(err)
}
}
这是另一次尝试失败并出现相同的错误消息:
fn read_utf8(self: &mut Parser<'a>, len: usize) -> Result<String, ParseError> {
self.consume_bytes(len)
.and_then(|bytes| String::from_utf8(bytes.to_vec()))
.map_err(|e| From::from(e))
}
这个版本map_err
里面 and_then
lambda,有效:
fn read_utf8(self: &mut Parser<'a>, len: usize) -> Result<String, ParseError> {
self.consume_bytes(len)
.and_then(|bytes| String::from_utf8(bytes.to_vec()).map_err(|e| From::from(e)))
}
为什么and_then
没有按预期工作?
PS:更具惯用性:我试图在上面编写或使用?
运算符/ try!
宏的版本?
fn read_utf8(self: &mut Parser<'a>, len: usize) -> Result<String, ParseError> {
let bytes = self.consume_bytes(len)?;
Ok(String::from_utf8(bytes.to_vec())?)
}
答案 0 :(得分:2)
我原本希望转换能够自动执行,因为使用
try!
宏可以自动转换(根据我的理解)。
但你并没有使用 try!
宏!
fn read_utf8(self: &mut Parser<'a>, len: usize) -> Result<String, ParseError> {
self.consume_bytes(len)
.and_then(|bytes| String::from_utf8(bytes.to_vec()))
}
谢天谢地,你打电话的代码不会对你的代码产生任何影响。
查看Result::and_then
的签名:
fn and_then<U, F>(self, op: F) -> Result<U, E>
where F: FnOnce(T) -> Result<U, E>
它需要一个闭包,返回Result
,其中包含我们开始的相同的错误类型。这里没有自动转换错误类型。 可能是成功类型的一些转换,具体取决于闭包选择做什么。
这就是您在and_then
中转换错误类型的版本有效的原因,因为您已将错误类型从FromUtf8Error
转换为ParseError
,从而使错误类型返回闭包与and_then
期望的匹配。