financial_physician
financial_physician

Reputation: 1978

Returning an iterator type defined in another crate

I'm trying to forward an iterator through a function to give constructing the iterator a more friendly interface.

This was an attempt that didn't quite work

pub fn rep_cartesian_product<'a, T>(iter: T, n: i32)-> itertools::MultiProduct<T> 
where T: Iterator + Clone {
    (0..n).map(|_| iter).multi_cartesian_product()
}

One of the errors I get is:

"The trait std::clone::Clone is not implemented for <T as std::iter::Iterator>::Item". But I'm not sure why this is the case since I put + Clone in the where clause.

A prior attempt was

pub fn rep_cartesian_product<'a, T>(iter: T, n: i32)-> impl Iterator<Item = Vec<T>>
where T : Iterator {
    (0..n).map(|_| iter).multi_cartesian_product()
}

type mismatch resolving <itertools::MultiProduct<T> as std::iter::Iterator>::Item == std::vec::Vec<T> which is why I tried the previous shared attempt.

Upvotes: 0

Views: 90

Answers (1)

user4815162342
user4815162342

Reputation: 155046

You requested that the iterator be Clone, but you additionally need to request that the items it produces are themselves Clone with a trait bound like T::Item: Clone.

Additionally, (0..n).map(|_| iter) doesn't compile because map() expects a closure it can call multiple times, and returning iter makes the closure callable only once. You can fix that by switching to .map(|_| iter.clone()) - or by using std::iter::repeat() instead.

Here is a version that compiles:

pub fn rep_cartesian_product<T>(iter: T, n: usize) -> itertools::MultiProduct<T>
where
    T: Iterator + Clone,
    T::Item: Clone,
{
    std::iter::repeat(iter).take(n).multi_cartesian_product()
}

Note that you can also return impl Iterator<Item = Vec<T::Item>>, which has the advantage of hiding the implementation of the iterator.

Upvotes: 3

Related Questions