admin管理员组文章数量:1336311
I'm very new to rust, so I concede off the bat that there may be a better third way to do this, but I'm very interested in what someone more experienced with the language has to say.
Given a generic function with signature:
fn process_lines<T: BufRead + Sized>(reader: T, re: Regex) {
What is the more "conventional" rust approach to calling this?
There is the straight forward approach:
match input {
"-" => {
let stdin = io::stdin();
process_lines(stdin.lock(), re)
}
_ => {
let f = File::open(input).unwrap();
process_lines(BufReader::new(f), re)
}
};
In other languages I would avoid writing out function calls multiple times by doing something that I think would translate as this:
let reader: Box<dyn BufRead> = match input {
"-" => {
let stdin = io::stdin();
Box::new(stdin.lock())
}
_ => {
let f = File::open(input).unwrap();
Box::new(BufReader::new(f))
}
};
process_lines(reader, re);
Is there a better way to construct reader
other than calling Box ?
This is a super trivial situation, but I'm worried I am falling into some kind of mental trap doing things the way I'm accustomed to...
I understand there is a some performance penalty for using Box... but I would imagine this is more of a problem inside some sort of nested control flow.
Which of these patterns scales better in large rust code bases, or it is always a per case kind of call?
Any and all insights on this dichotomy (or false dichotomy if there is indeed a third way) are really appreciated!
I'm very new to rust, so I concede off the bat that there may be a better third way to do this, but I'm very interested in what someone more experienced with the language has to say.
Given a generic function with signature:
fn process_lines<T: BufRead + Sized>(reader: T, re: Regex) {
What is the more "conventional" rust approach to calling this?
There is the straight forward approach:
match input {
"-" => {
let stdin = io::stdin();
process_lines(stdin.lock(), re)
}
_ => {
let f = File::open(input).unwrap();
process_lines(BufReader::new(f), re)
}
};
In other languages I would avoid writing out function calls multiple times by doing something that I think would translate as this:
let reader: Box<dyn BufRead> = match input {
"-" => {
let stdin = io::stdin();
Box::new(stdin.lock())
}
_ => {
let f = File::open(input).unwrap();
Box::new(BufReader::new(f))
}
};
process_lines(reader, re);
Is there a better way to construct reader
other than calling Box ?
This is a super trivial situation, but I'm worried I am falling into some kind of mental trap doing things the way I'm accustomed to...
I understand there is a some performance penalty for using Box... but I would imagine this is more of a problem inside some sort of nested control flow.
Which of these patterns scales better in large rust code bases, or it is always a per case kind of call?
Any and all insights on this dichotomy (or false dichotomy if there is indeed a third way) are really appreciated!
Share edited Nov 19, 2024 at 18:55 dumbass 27.3k4 gold badges37 silver badges74 bronze badges asked Nov 19, 2024 at 18:35 Niall ByrneNiall Byrne 2,4601 gold badge18 silver badges19 bronze badges 3 |1 Answer
Reset to default 2Temporary lifetime extension has been landed in rust 1.79, which makes it possible to write this:
let reader: &mut dyn BufRead = match input {
"-" => &mut std::io::stdin().lock(),
_ => {
let file = std::fs::File::open(input).unwrap();
&mut std::io::BufReader::new(file)
}
};
process_lines(reader, re);
Temporary values that are generated in if
, match
, and raw blocks, with borrows that escape the scope of the block, would have extended lifetime to match the borrows' lifetime.
This is useful for many dynamic dispatch cases, which are not supported in the earlier versions.
本文标签:
版权声明:本文标题:rust - How to avoid repetitive calls to a function with arguments of different types fitting the same generic parameter? - Stack 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742405837a2468798.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
process_lines(create_reader(input), re)
? But I'd probably end up using Box again ... – Niall Byrne Commented Nov 19, 2024 at 18:39enum impl Trait
in discussions – see for example <internals.rust-lang./t/…>. – dumbass Commented Nov 19, 2024 at 18:43Box
overhead by using&mut dyn io::BufRead
instead. Declarelet (mut r0, mut r1);
in a scope containing theprocess_lines
call, then have each match arm assign to eitherr0
orr1
and return a&mut
to that variable. Then pass that reference as the argument toprocess_lines
. – dumbass Commented Nov 19, 2024 at 18:53