Iterator's operator overloading with map

Hello All

Is there any way to do something like this ?

#[cfg(test)]
mod t {
    use std::iter::Map;
    use std::ops::{Mul, Range};

    impl<I: Iterator, F> Mul for I {
        type Output<F> = Map<I, F>;

        fn mul(self, mut rhs: Self) -> Self::Output<F> {
            self.map(|x| x * rhs.next().unwrap())
        }
    }
    #[test]
    fn io() {
        let m = vec![1, 2, 3] * vec![2, 3, 4];
    }
}

Of course the error comes from the Function type, which is not really generic, but I don't know how to do ?
error[E0207]: the type parameter Fis not constrained by the impl trait, self type, or predicates

continuing the experimentation, I have something different here

#[cfg(test)]
mod t {
    use std::iter::Map;
    use std::ops::{Mul, Range};

    impl<I: Iterator> Mul for I {
        type Output = Self;

        fn mul(self, mut rhs: Self) -> Self::Output {
            self.zip(rhs).map(|(a, b)| a * b)
        }
    }
    #[test]
    fn io() {
        let m = vec![1, 2, 3] * vec![2, 3, 4];
    }
}
error[E0119]: conflicting implementations of trait `std::ops::Mul` for type `u32`:
  --> src\traits\ops.rs:10:5
   |
10 |     impl<I: Iterator> Mul for I {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: conflicting implementation in crate `core`:
           - impl std::ops::Mul for u32;
   = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `u32` in future versions

error[E0210]: type parameter `I` must be used as the type parameter for some local type (e.g., `MyStruct<I>`)
  --> src\traits\ops.rs:10:10
   |
10 |     impl<I: Iterator> Mul for I {
   |          ^ type parameter `I` must be used as the type parameter for some local type
   |
   = note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
   = note: only traits defined in the current crate can be implemented for a type parameter

Rustc here complains about the fact that another crate could also have implemented the trait if it allows this implementation. Because this would cause big problems, you are only allowed to implement a trait if either the trait or the type you implement it on is defined in the current crate. (the rules are a bit more complex, but this is the basic rule) For the exact rules see RFC1023 and RFC2451.

allright,
so the solution is to wrap an Iterator into a 'dummy' struct

#[cfg(test)]
mod test {
    use crate::Line;
    use std::ops::Mul;

    struct Synth<I: Iterator>(I);
    struct MulSynth<I: Iterator, J: Iterator>(I, J);

    impl<I: Iterator> Iterator for Synth<I> {
        type Item = I::Item;
        fn next(&mut self) -> Option<Self::Item> {
            self.0.next()
        }
    }
    impl<I: Iterator<Item = f32>, J: Iterator<Item = f32>> Iterator for MulSynth<I, J> {
        type Item = I::Item;
        fn next(&mut self) -> Option<Self::Item> {
            match (self.0.next(), self.1.next()) {
                (Some(x), Some(y)) => Some(x * y),
                _ => None,
            }
        }
    }
    impl<I: Iterator<Item = f32>, J: Iterator<Item = f32>> Mul<Synth<J>> for Synth<I> {
        type Output = MulSynth<Synth<I>, Synth<J>>;

        fn mul(self, rhs: Synth<J>) -> Self::Output {
            MulSynth(self, rhs)
        }
    }

    #[test]
    fn io() {
        let m = Synth(Line::scalar(2.0)) * Synth(Line::scalar(3.0));
    }
}

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.