In rust it is generally considered most idiomatic to only have as many generics as axes of generality.
that is thankfully often the only possible option, like for example this :
fn g<F, I>(f: F, v: Vec<f64>) -> I
where
F: Fn(&[f64]) -> f64,
I: lterator<f64>,
{
v.windows(6).map(f)
}
does not compile, as the correct way to write this function is
fn g<F>(f: F, v: Vec<f64>) -> impl lterator<f64>
where
F: Fn(&[f64]) -> f64,
{
v.windows(6).map(f)
}
but with associated types, it is very easy to add superfluous generics to a function definition.
for example in the actual exercise in question, this :
pub fn length<I: Iterator<Item = T>, T>(_iter: I) -> usize
should obviously be
pub fn length<I: Iterator>(_iter: I) -> usize
in general, the T
s can be removed from all function definitions in that exercise, for a clearer, more idiomatic API.
pub fn append<I : Iterator, J>(fst: I, snd: J) -> impl Iterator<Item = I::Item>
where
J : Iterator<Item = I::Item>
pub fn concat<I: Iterator>(mut nested_iter: I) -> impl Iterator<Item = <I::Item as Iterator>::Item>
where
I::Item : Iterator
pub fn filter<I: Iterator, F>(iter: I, predicate: F) -> impl Iterator<Item = I::Item>
where
F: Fn(&I::Item) -> bool,
pub fn map<I: Iterator, U, F>(mut iter: I, function: F) -> impl Iterator<Item = U>
where
F: Fn(I::Item) -> U,
pub fn foldl<I : Iterator, U, F>(iter: I, initial: U, function: F) -> U
where
F: Fn(U, I::Item) -> U
pub fn foldr<I: DoubleEndedIterator, U, F>(mut iter: I, initial: U, function: F) -> U
where
F: Fn(U, I::Item) -> U
pub fn reverse<I: DoubleEndedIterator>(iter: I) -> impl Iterator<Item = I::Item>