Search code examples
c++c++20range-v3std-ranges

Make a range from Iterated function application


If I have a function

std::array<unsigned,2> fib(std::array<unsigned,2> p)
{
    return {p[1],p[1]+p[0]};
}

I'd like to have a way to elegantly generate the infinite range

[x,fib(x),fib(fib(x)),fib(fib(fib(x))),...]

This comes up frequently enough that I need to find what's the best way to do this?


Solution

  • I found that the generator from this repo works well:

    template<typename F, typename Arg>
    tl::generator<Arg> iterated_application(F fn, Arg x) {
        while (true) {
            co_yield x;
            x = fn(x);
        }
    }
    

    Which can be used as

    int main() 
    {
        auto fib = [](auto a) {return std::array{ a[1],a[1] + a[0] }; };
        for (auto i : iterated_application(fib, std::array{ 0,1 }) 
            | std::views::keys 
            | std::views::take(10))
        std::cout << i << std::endl;
    }
    

    https://godbolt.org/z/v73zvY9cM