I have problem understanding why I cannot return my reader form a function. Example:
use std::io::{prelude::*, Read, BufReader};
use std::fs::File;
fn get_reader<R: Read>(file:&str)-> BufReader<R>{
let mut fin;
let read: &mut dyn Read = match file {
_ => {
fin = File::open(file).expect(&(format!("Error opening {} file",file)));
&mut fin
}
};
let mut reader = BufReader::new(read);
reader
}
fn main() {
let mut r = get_reader("log.txt");
for l in r.lines(){
//blah
}
}
the example is truncated to simplify a real scenario which has several matching conditions.
read has type &mut dyn Read, so BufReader::new(read) has type BufReader<&mut dyn Read>, not BufReader<R>.
Furthermore, by returning something that wraps the pointer to fin, you'd be trying to return the address of a local variable anyway, which is an error. I'm wondering why you don't just return BufReader<File> by wrapping the file object into the BufReader directly (by value)? It doesn't seem you need the generic type parameter R at all. I.e.:
It also looks like you're not clear on what the difference between generics and dyn Trait is, and/or why one wants to use generics in general. I'd suggest reading up more on that.
well when I fix it i get cannot return value referencing local variable 'fin' And Yes I am not sure ... Still learning and therefore when you or someone else here gives me pointers (like you did) I know where to look, it help enormously ... Thank you !
Update: Maybe i framed it incorrectly and did not read your post thoroughly ... just a sec before reading further ...
And it does but what if I wanna return a Read from stdin but I do not know what I want to do at compile time:
let mut stdin;
let mut fin;
let read: &mut dyn Read = match file {
"stdin" => {
stdin = io::stdin();
&mut stdin
},
_ => {
fin = File::open(file).expect(&(format!("Error opening {} file",file)));
&mut fin
},
"I have several other 'dubious' conditions here" => {}
};
let reader = BufReader::new(read);
reader
Then you do need a trait object, indeed. However, you still want to return by-value, which you can achieve using Box<dyn Read>, and in turn BufRead<Box<dyn Read>>, e.g.:
let read: Box<dyn Read> = match file {
"stdin" => Box::new(io::stdin()),
_ => Box::new(File::open(file).expect("…")),
};
BufReader::new(read)