I'm still kind of new to Rust, trying to wrap my head around parts of it. As an exercise I tried to make it possible to create iterators like this (in this case for the Fibonacci sequence):
(1,1).iterize(|p| (p.1, p.0 + p.1))
You specify a tuple with the first two values, and a function that takes that and produces the tuple for the next iteration. The Iterator just calls the function repeatedly and returns the old tuple.0 values.
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> src/main.rs:31:36
|
31 | fn iterize(&mut self, f: F) -> impl Iterator<Item = R>; // E0562
| ^^^^^^^^^^^^^^^^^^^^^^^
Does that mean that trait methods are not allowed to return impl traits? If so, is there another efficient (I assume using dyn would drastically impact performance) way to do what I am trying to do?
Note that this means you must be able to write the type down, so you cannot use iterators that have a closure as a generic parameter, as the type of the closure cannot be named.
I came to the conclusion that this wasn't going to work with the API I had imagined, so I made iterize() a plain function, and that works:
fn main() {
dbg!(fib().take(6).collect::<Vec<i32>>());
}
// Returns an Iterator for the Fibonacci sequence: 1 1 2 3 5 8 ...
fn fib() -> impl Iterator<Item = i32> {
iterize((1,1), |p| (p.1, p.0 + p.1))
}
// Given an initial state of type (R,S) and a function that produces a new state
// from an old state, return an Iterator for the Rs.
fn iterize<R: Copy, S: Copy>(s0: (R,S), f: impl Fn((R,S)) -> (R,S)) -> impl Iterator<Item = R> {
let mut state = s0;
std::iter::repeat_with(
move || { state.swap(f(state)).0 }
)
}
// a.swap(b) sets a to b and returns the old value of a.
pub trait Swap: Sized {
fn swap(&mut self, value: Self) -> Self;
}
impl<T> Swap for T {
// Sets self to the new value and returns the old value.
fn swap(&mut self, new: Self) -> Self {
std::mem::replace(self, new)
}
}