The List Ops uses unidiomatic function signatures

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 Ts 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> 

This is a good suggestion, a PR is in the works.

2 Likes