unfold

Haskellなどにあるunfoldは、reduceの逆で初期値からリストを作っていきます。

f(状態0) → (値1, 状態1) → 値1
f(状態1) → (値2, 状態2) → 値2

という具合に値を出していきます。
reduceの逆なのにunfoldなのはあまり気にしない方向で。

template<typename T, typename U, typename V>
class cUnfold : public cIterable<T> {
    T   val;
    U   stat;
    V   func;
    
public:
    cUnfold(V f, U s) : stat(s), func(f) { }
    
    bool exists_next() {
        pair<T,U>   p = func(stat);
        val = p.first;
        stat = p.second;
        return true;
    }
    T value() const { return val; }
};

template<typename U, typename V>
auto unfold(V f, U s) -> shared_ptr<cIterable<decltype(f(s).first)>> {
    typedef decltype(f(s).first)    T;
    return shared_ptr<cIterable<T>>(new cUnfold<T,U,V>(f, s));
}

これで、フィボナッチ数列が簡単に作れます。

shared_ptr<cIterable<int>> fib() {
    typedef pair<int,int>   T;
    auto    f = [] (T s) { return pair<int,T>(s.second,
                                T(s.second, s.first + s.second)); };
    return unfold(f, T(1, 1));
}