As an exercism exercise, I'm currently trying to filter an iterator according to whether the value is even in order to produce a new iterator.
My function currently looks like:
pub fn evens<T>(iter: impl Iterator<Item = T>) -> impl Iterator<Item = T>
where T: std::ops::Rem<Output = T>
{
iter.filter(|x| x % 2 != 0)
}
But this won't compile because:
error[E0369]: cannot mod `&T` by `{integer}`
--> src/lib.rs:4:23
|
4 | iter.filter(|x| x % 2 != 0)
| - ^ - {integer}
| |
| &T
|
help: consider further restricting this bound
|
2 | where T: std::ops::Rem<Output = T> + std::ops::Rem<Output = {integer}>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
However, I know I can't simply change this to
pub fn evens<T>(iter: impl Iterator<Item = T>) -> impl Iterator<Item = T>
where T: std::ops::Rem<Output = T> + std::ops::Rem<Output = {integer}>
{
iter.filter(|x| x % 2 != 0)
}
as this fails to compile with:
error: cannot constrain an associated constant to a value
--> src/lib.rs:2:56
|
2 | where T: std::ops::Rem<Output = T> + std::ops::Rem<Output = {integer}>
| ------^^^---------
| | |
| | ...cannot be constrained to this value
| this associated constant...
I'm vaguely aware of some "Num" traits, but the exercism doesn't seem to accept answers which require importing dependencies through Cargo.toml, so I'm looking for a native/built-in solution.
Any ideas how I can make this work?
(P.S. I've now figured out that I misunderstood the exercise, where "even" describes the enumerated index, not the value... but never mind. I'd still like to know whether/how this could be made to work.)
The easiest way without third party libraries is to convert the constant into T
explicitly:
use core::convert::TryFrom;
pub fn evens<T>(iter: impl Iterator<Item = T>) -> impl Iterator<Item = T>
where T: Eq + Copy + std::ops::Rem<Output=T> + TryFrom<i32>
{
let zero = T::try_from(0).ok().unwrap();
let two = T::try_from(2).ok().unwrap();
iter.filter(move |x| *x % two != zero)
}