I've been following a Rust tutorial where two versions of a function are purported to generate the same results:
pub fn get_transactions(fname:&str) -> Result<Vec<Transaction>,String> {
let s = match std::fs::read_to_string(fname){
Ok(v)=>v,
Err(e)=> return Err(e.to_string()),
};
let t:Vec<Transaction> = match serde_json::from_str(&s) {
Ok(v)=>v,
Err(e)=> return Err(e.to_string()),
};
Ok(t)
}
fn get_transactions_b(fname:&str) -> Result<Vec<Transaction>,String> {
std::fs::read_to_string(fname)
.map_err(|e| e.to_string())
.and_then(|ld| serde_json::from_str(&ld) )
.map_err(|e| e.to_string())
}
mismatched types
expected struct std::string::String
, found struct serde_json::error::Error
note: expected enum std::result::Result<_, std::string::String>
found enum std::result::Result<_, serde_json::error::Error>
help: try using a variant of the expected enum: _::_serde::export::Ok(serde_json::from_str(&ld))
,
which I been unable to make head or tail out of:
Hovering over ld closure argument |ld|
in VS Code it says it's of type std::string::String
Hovering over the ld in the from_str(&ld)
I get the message.
Now I understand a Result
is comprised of an Ok
and an Err
, but I thought the combinator chaining would have worked.
The compiler suggested fix doesn't work either.
_::_
all about?Ok
not be inside the from_str?What would you have to do to make version 2 work?
Here's the Result with the methods for combinators in the Rust docs.
[dependencies]
serde = "1.0.115"
serde_derive = "1.0.115"
serde_json = "1.0.57"
A combinator is a function which builds program fragments from program fragments; in a sense the programmer using combinators constructs much of the desired program automatically, rather that writing every detail by hand. The exact definition of “combinators” in Rust ecosystem is bit unclear. Convert type T by applying a closure.
Rust also provides map () as an iterator adaptor to apply a closure on each element of an iterator to transform it into another iterator. However in here we are talking about the functionality of map () with Option and Result types.
One meaning of “combinator” is a more informal sense referring to the combinator pattern, a style of organizing libraries centered around the idea of combining things.
The problem comes from the and_then
call.
You are not allowed to change the error type when calling and_then
.
So your function there should return a Result<Vec<Transaction>, String>
. However, the error type returned by serde_json::from_str
is a serde_json::error::Error
.
You can fix it like this:
std::fs::read_to_string(fname)
.map_err(|e| e.to_string())
.and_then(|ld| serde_json::from_str(&ld).map_err(|e| e.to_string()))
Notice the call to map_err
is now inside the function passed to and_then
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With