2012-08-03

SCIP in C++11 ― 1.3.4節 その4


手続きの合成:問題1.41~問題1.44

手続きの合成の一般的な記述とかよくわからなくて結構ハマる。
頼みの綱は、「C++11というかboostを作った変態魔法使いたちが、
10年以上前に出て以来業界でめちゃんこ有名なSICPの、
1章に出てる程度のことを簡単に実装できないようなライブラリを作るはずがない。
出来ないのは自分の理解がまずいのだ。」という、
最後の部分以外はあまり根拠のない思い。

それでなんとかScheme
((double (double (double inc))) 5)にあたるものは作れるようになったが、
(double double)はつまづく。
autoとかテンプレートとかfunctionラッパとかごちゃ混ぜで、
いい加減に使っていたから、なんかテンプレートの記述がえらいぐちゃぐちゃしてくる。

とりあえず何とかcomposeの実装らしきものはできたから、
あとはまたの機会にアレキサンドレスクでも見ながら考えるしかないか・・・
と思っていたら早速問題1.43repeatの再帰実装でつまづく。
再帰が入ると、関数の型の扱いがいい加減だと
テンプレート型がバースト的に肥大化するようなので、
いい加減にやっていたら誤魔化しが効かない。

LINK
アレキサンドレスク
Modern C++ Design
アレクサンドレスクで言うチェインを実装しないといけない。
でもまた根拠無く「アレクサンドレスクは有名なド変態魔術書だが10年以上前の本。
アレクサンドレスクのあとのboostの進化で、Lokiで出来ることはきっと組み込まれいて、
C++11に生かされているはず。自分が知らないだけ!」と思い込むことにする。
まずはfunctionラッパをメインに据えて、
1.3.1節からすべてのプログラムを書きなおす。
すこしfunctionラッパの使い方が見えてきたか。

問題1.41(double double)
C++ではdoubleは使えないからdoublingという名にした)
最初にdoubling2重化する型を具体的に解決するトリガーが必要で、
まだ完全ではない。が、よくよく考えてみれば、repeatでは繰り返し回数が変数だが、
doubling2回とわかっているのだから、
テンプレートで解決できるはずじゃないかと思うが、
(doubling(doubling(doubling<int>)))(inc)(5)
とかやってもうまくパターンマッチしないなあ。

----
template<typename FReturn,typename FArgument,
         typename GReturn,typename GArgument>
const function<FReturn(GArgument)>
compose(const function<FReturn(FArgument)>& f,
        const function<GReturn(GArgument)>& g)
{
    using namespace std::placeholders;
    return(bind(f, bind(g, _1)));
}

template<typename ReturnType>
const function<ReturnType(ReturnType)>
repeated(const function<ReturnType(ReturnType)>& f,const int n)
{
    const function<ReturnType(ReturnType)>
        identity=[](const ReturnType x){return(x);};
    if(0==n){return(identity);}
    else if(1==n){return(f);}
    else{return(compose(f,repeated(f,n-1)));}
}



template<typename ReturnType>
const function<ReturnType(ReturnType)>
doubling(const function<ReturnType(ReturnType)>& f)
{
    //return(compose(f,f));
    return(repeated(f,2));
}


const int increment(const int i){return(i+1);}

template<typename ResultType>
const ResultType squareFun(const ResultType x){return(x*x);}

const function<double(double)>
smoothNTime(const function<double(double)>& f,
            const double smoothLength, const int n)
{
    function<function<double(double)>(function<double(double)>)>
        smooth1Time;
    smooth1Time=[smoothLength](const function<double(double)>& f){
        return([f,smoothLength](const double x)
        {return((f(x-smoothLength)+f(x)+f(x+smoothLength))/3.0);});
    };
    return(repeated(smooth1Time,n)(f));
}
const function<double(double)>
smooth(const function<double(double)>& f,
       const double smoothLength)
{
    return(smoothNTime(f,smoothLength,1));
}



int main(int argc, char** argv)
{
    const function<int(int)> inc=increment;
    const function<function<int(int)>(function<int(int)>)>
        doublingInt=doubling<int>;

    cout<<"Excersize 1.41:"<<endl;
    cout<<"((double inc) 5)="<<(doubling(inc))(5)<<endl;
    cout<<"(((double (double double)) inc) 5)="
        <<(doubling(doubling(doublingInt)))(inc)(5)<<endl;
    //cout<<(doubling(doubling(doubling<int>)))(inc)(5)<<endl;

    cout<<endl<<"Excersize 1.42:"<<endl;
    const function<int(int)> square=squareFun<int>;
    cout<<"((compose square inc) 6)="
        <<compose(square,inc)(6)<<endl;

    cout<<endl<<"Excersize 1.43:"<<endl;
    const function<double(double)> dsquare=squareFun<double>;
    cout<<"((repeated square 2) 5)="
        <<repeated(dsquare,2)(5.0)<<endl;

    cout<<endl<<"Excersize 1.44: data is put out to files."<<endl;
    ofstream outFile("out.txt");
    ofstream outFile1("out1.txt");
    ofstream outFile5("out5.txt");
    const double dx=2.0;
    const double smoothLength(1.0);
    const function<double(double)> f=
        [](const double y){return(sin(y));};
    for(int ix=0;ix<100;++ix){
        const double x(dx*ix);
        outFile<<x<<" "<<f(x)<<endl;
        outFile1<<x<<" "<<smooth(f,smoothLength)(x)<<endl;
        outFile5<<x<<" "<<smoothNTime(f,smoothLength,5)(x)<<endl;
    }
    outFile.close();
    outFile1.close();
    outFile5.close();

    return(0);
}
----
出力
----
Excersize 1.41:
((double inc) 5)=7
(((double (double double)) inc) 5)=21

Excersize 1.42:
((compose square inc) 6)=49

Excersize 1.43:
((repeated square 2) 5)=625

Excersize 1.44: data is put out to files.


0 件のコメント :

コメントを投稿