## Exercising Ranges (part 5)

(Start at the beginning of the series if you want more context.)

Generalising `iota`

To pretty-print a reversible polynomial, we need to provide for reversibility of `iota`. So what is `iota`? It makes a range by repeatedly incrementing a value. What if instead of increment, we use an arbitrary function? We could do this with `generate_n`:

```template <typename Rng> std::string to_string_reverse(Rng&& r) { auto s = ranges::size(r); auto powers = ranges::view::generate_n( [s] () mutable { return --s; }, s); return detail::to_string( ranges::view::zip(ranges::view::reverse(std::forward<Rng>(r)), powers)); }```

But this isn’t quite as clean as it could be: the lambda mutates state. An alternative is found in the Haskell Prelude:

`iterate :: (a -> a) -> a -> [a]`

`iterate` applies a function repeatedly to an argument, feeding the result of the last iteration to the input of the next one. It’s very similar to `generate`, and we can write both `iterate` and `iterate_n`. The view takes a function and an initial value, and produces the sequence:

$x, f(x), f(f(x)), f(f(f(x))), ...$

Here’s the C++ for the skeleton of `iterate_view`:

```template<typename G, typename T> struct iterate_view : view_facade<iterate_view<G, T>, infinite> { private: friend struct range_access; using result_t = concepts::Function::result_t<G, T>; semiregular_t<G> gen_; semiregular_t<result_t> val_; ... explicit iterate_view(G g, T&& t) : gen_(std::move(g)), val_(std::move(t)) {} ... };```

The cursor is easily written just like `generate`‘s cursor: `next()` caches a new value, and `current()` returns it. Like `generate`, the view can only be traversed once, so the cached value is kept in the view itself rather than the iterator. And there is no end cursor.

```struct cursor { iterate_view *view_; ... result_t current() const { return view_->val_; } void next() { view_->next(); } }; void next() { val_ = gen_(val_); }```

For `iterate_n`, the approach is almost identical, except that `next()` decrements a count, and `size()` is also provided. Using `iterate_n`, we can generate a decreasing sequence and use it in the reverse print function for a polynomial, which we know is a `SizedRange`.

```template <typename Rng> std::string to_string_reverse(Rng&& r) { auto s = ranges::size(r); auto powers = ranges::view::iterate_n( [] (auto i) { return i - 1; }, s-1, s); return detail::to_string( ranges::view::zip(ranges::view::reverse(std::forward<Rng>(r)), powers)); }```

As for `iterate` itself, it’s potentially useful in lots more places. The obvious use cases (and test cases) are mathematical in nature, for instance my test case using the Collatz conjecture (aka Ulam conjecture, 3n+1 conjecture) sequence starting with 27:

```int collatz(int n) { if (n & 1) return 3*n+1; return n>>1; }   DEF_TEST(Collatz27, Iterate) { auto m = view::iterate(collatz, 27) | view::take_while([] (int n) { return n != 1; }); EXPECT(ranges::find(m, 9232) != ranges::end(m)); return true; }```

But there are also plenty of applications in other code, where we are updating the state of something based on its previous state: `iterate` separates the loop code and allows us to write a clean function that simply produces a new state from an old state. This is useful for games and simulations of all kinds. So `iterate` is a useful addition to the range views.

Now we can pretty-print polynomials properly, in the next part I’m going to take on the trickier subject of how to multiply them.