When a function takes a series of values as a parameter, is it considered good style to accept an Iterator<T>
instead of Vec<T>
?
This way, the caller can decide on their own how the series is stored (inside a Vec
, a [T; N]
or anything else, actually an Option<T>
should be possible!). Also, this eliminates the need to convert the whatever you have into a Vec
, and also, after applying some Iterator modifiers, no .collect()
is needed! So it should also be faster!
Am I missing something or is this the way it should be done?
Such a function as you describe should typically generically take an IntoIterator<Item = T>
; thus it can accept both Iterator<T>
and Vec<T>
as input.
This can be combined with other techniques, too; for example, this method concat
will accept a &[&str]
(and thus &Vec<&str>
by auto deref/ref coercion), &[String]
(and thus &Vec<String>
), a &str
iterator, a String
iterator, et cetera:
use std::borrow::Borrow;
fn concat<T: Borrow<str>, Iter: IntoIterator<Item = T>>(iter: Iter) -> String {
iter.into_iter() // -> impl Iterator<Item = T>
.map(|s| s.borrow()) // -> impl Iterator<Item = &str>
.collect() // -> String
}
(This specific example would actually typically be better suited to SliceConcatExt
, because it’s able to calculate how long the final result will be up front and thus allocate the right length string all at once. But it’s just a proof of the concept and how multiple fancy techniques can be combined.)
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