I would like to create a method similar to the collect_vec()
function in itertools
.
Creating a small example by copying the itertools
code:
pub trait MyItertools: Iterator {
fn collect_vec(self) -> Vec<Self::Item>
where Self: Sized
{
self.collect()
}
}
fn main() {
let v = (0..5).collect_vec();
println!("{:?}", v);
}
I rather naively expect that the compiler will use my collect_vec
as
MyItertools
is in scope.
There must be some other magic that itertools
is doing to get this to compile.
We get the error:
error[E0599]: no method named `collect_vec` found for struct `std::ops::Range<{integer}>` in the current scope
--> src/main.rs:14:20
|
14 | let v = (0..5).collect_vec();
| ^^^^^^^^^^^ method not found in `std::ops::Range<{integer}>`
|
= help: items from traits can only be used if the trait is implemented and in scope
note: `MyItertools` defines an item `collect_vec`, perhaps you need to implement it
--> src/main.rs:5:1
|
5 | pub trait MyItertools: Iterator {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
Which is misleading as we have indeed implemented collect_vec
in MyItertools
.
One possible solution is to impl MyItertools
for all flavours of
Iterator
, but there does not seem to be a way to do this for all Iterator
implementing traits and types.
The missing magic piece of the puzzle is a generic blanket implementation that implements the MyItertools
trait for all types which implement the Iterator
trait. Updated fixed example:
pub trait MyItertools: Iterator {
fn collect_vec(self) -> Vec<Self::Item>
where Self: Sized
{
self.collect()
}
}
impl<T> MyItertools for T where T: Iterator {}
fn main() {
let v = (0..5).collect_vec();
println!("{:?}", v);
}