gpt4 book ai didi

rust - 为什么在使用 and_then 组合器时我的错误类型没有自动更改?

转载 作者:行者123 更新时间:2023-11-29 08:27:22 25 4
gpt4 key购买 nike

我遇到了关于 ResultFromand_then 的一些我不理解的事情。

我的 impl Parser 中有这个函数,当没有足够的字节时,它会给我一个 byte slice 段或一个 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! 宏,转换是自动的(从什么我明白了):

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_errinside 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())?)
}

最佳答案

I was expecting the conversion to be performed automatically, since by using the try! macro the conversion is automatic (from what I've understood).

但是你没有使用 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 期望的相匹配。

关于rust - 为什么在使用 and_then 组合器时我的错误类型没有自动更改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42330159/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com