I'm having a misunderstanding about return types in rust. coming from JavaScript and thinking I understood the core concepts of mutating, scopes, etc. But now I'm stuck at a simple return type.
fn main() {
let input = "./assets/input.csv";
let list = get_csv(&input);
for result in list.records() {
let record = result?;
println!("{:?}", record);
}
}
fn get_csv(csv_path: &str) -> csv::Reader {
return csv::Reader::from_path(csv_path);
}
I will get the error
mismatched types
expected struct `csv::Reader`, found enum `std::result::Result`
note: expected struct `csv::Reader<&str>`
found enum `std::result::Result<csv::Reader<std::fs::File>, csv::Error>`
note: to return `impl Trait`, all returned values must be of the same type
note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
help: you could instead create a new `enum` with a variant for each returned typerustc(E0308)
UPDATE:
fn get_csv (filepath: &str) -> csv::Result<csv::Reader<File>>{
let mut reader = csv::ReaderBuilder::new();
let mut list = match reader
.delimiter(b';')
.from_path(&filepath) {
Ok(list) => list,
Err(error) => {
println!("Failed to open file. {}", error);
return;
}
};
return list;
}
The error message is telling you that what the method returns (Result
) is different from what you have defined (csv::Reader
). When you check the documentation for the from_path
method, you see that it is defined as:
pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Reader<File>>
The return value of the function is a Result
enum that has two states: Ok
or Err
. If for example the given file doesn't exist, you cannot create a reader for it. In your code, you have to handle the case that the reader cannot be created. For example:
use csv::Reader;
fn main() {
let input = "./assets/input.csv";
let mut list = match Reader::from_path(&input) {
Ok(list) => list,
Err(error) => {
println!("Failed to open file. {}", error);
return;
}
};
for result in list.records() {
let record = result.unwrap();
println!("{:?}", record);
}
}
The Rust book has more information on the Result
enum: https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html
The Reader
that gets returned in the Result
is a generic type, which means that it provides a generic implementation that can be used with different concrete Rust types. Reader<File>
is the notation that tells the Rust compiler that this instance of Reader
is used to read from a File
. But technically, Reader
supports anything that implements the std::io::Read
trait (see the source). For example, you could use to read CSV files from a network stream, or have the user type them into STDIN
and read them from the terminal line-by-line.