pstade::oven::cycled をしたときに連続して展開して欲しい。


[お題]
pstade::oven::cycled した時に、連続して展開して欲しい。
言葉にするとややこしいんですが、こんな感じです。

{0, 1, 2}|pstade::oven::cycled(4);
// {0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2}
//
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
//
// こんな感じで展開して欲しい
// {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2} 
#include <iostream>

#include <pstade/oven/cycled.hpp>
#include <pstade/oven/transformed.hpp>
#include <pstade/oven/matrix.hpp>
#include <pstade/oven/concatenated.hpp>
#include <pstade/oven/io.hpp>
#include <pstade/oven/distance.hpp>

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

int
main(){
    namespace oven = pstade::oven;
    namespace lambda = boost::lambda;
    
    int array[] = {0, 1, 2};
    
    std::cout << (array|oven::cycled(4)) << std::endl;

    std::cout <<
        (array
            |oven::rows(array|oven::distance, 1)
            |oven::transformed(lambda::bind(oven::make_cycled, lambda::_1, 4))
            |oven::concatenated)
    << std::endl;

    return 0;
}


[出力]

{0,1,2,0,1,2,0,1,2,0,1,2}
{0,0,0,0,1,1,1,1,2,2,2,2}


さて、順を追って説明すると、まず最初に pstade::oven::rows を使用して2次元配列に展開しなおします。
第一引数に range の長さを指定。

{0, 1, 2}|rows(3, 1); // { {0}, {1}, {2} }


次に pstade::oven::transformed を使用して、それぞれの要素に対して pstade::oven::cycled を適用しています。
ここで、boost::lambda を使って、ごにょごにょしていますが、

lambda::_1|cycled(4)

の様な処理をしていると思ってください。

{ {0}, {1}, {2} }|transformed(lambda::bind(make_cycled, lambda::_1, 4))
// { {0, 0, 0, 0}, {1, 1, 1, 1}, {2, 2, 2, 2} }


このままでは2次元配列になっているので、最後に pstade::oven::concatenated を使用して、1次元配列に戻します。

{ {0, 0, 0, 0}, {1, 1, 1, 1}, {2, 2, 2, 2} }|concatenated;
// { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2 }


これで完成!
ソースだけ見るとごにょごにょしていますが、実際はそんなに難しいことをしていません。
ようは組み合わせですねー。
range 面白いです。
pstade の中に似たようなアダプタがあるかは知らない。


[pstade]
ver 1.04.3