2012-10-02

SCIP in C++11 ― 3.3.3節その2


局所表の表現・透過性テストの選択と表の多次元化:問題3.24~問題3.253.25は難儀中)

2章で重要な役割を果たしたget,putの、
メッセージパッシング実装。
問題3.24までは問題なし。

だが問題3.25がうまくいかない。
lookupinsert!が再帰クロージャにならないといけないのだが、
再帰が入ると、クロージャが自分自身への参照をキャプチャして、
かつクロージャの関数オブジェクトを保持し続ける、
ということが出来なければならない。
が、キャプチャするのが関数オブジェクトの参照で、その参照元は、
宣言したところの寿命が尽きると死ぬから、2つの条件が両立しない・・・
関数オブジェクトをわざわざ別関数のスタックに入れて右辺値参照するとか、
いろいろやってみたがうまくいかない。
再帰でないなら難しくないのだけど。

大域変数にするとか、全然関係ない場所に保持させるとかっていう手は、
危険だし使いものにならないから使いたくないし・・・。
そろそろC++でやる限界が近づいてきたか?
せめて回路シミュレータはやりたいので、とりあえずそちらに行ってみる。

----
typedef function<List(List)> Table;

const List associate
(const List& key, const List& records,
 const function<bool(List,List)>& isSameKey)
{
    if(isNull(records)){return(makeList());}
    if(isSameKey(key,caar(records))){return(car(records));}
    return(associate(key,cdr(records),isSameKey));
}

const Table makeTableDispatch
(const List& initialTable,
 const function<bool(List,List)>& isSameKeyIn)
{
    const auto localTable(std::move(initialTable));
    const auto isSameKey(std::move(isSameKeyIn));

    function<List(List,List)> lookup;
    lookup=[isSameKey,lookup]
        (const List& keyList,const List& table){
        if(isNull(keyList)){
            cerr<<"no match --- LOOKUP"<<endl;
            return(makeList());
        }
        const auto subtable(associate(car(keyList),cdr(table),isSameKey));
        if(!isNull(subtable)){
            const auto record(associate(cadr(keyList),cdr(subtable),isSameKey));
            if(!isNull(record)){return(cadr(record));}
            return(makeList());
        }
            return(makeList());
    };
   
    function<List(List,List)> insertf;
    insertf=[localTable,isSameKey,insertf]
        (const List& keyList, const List& value){
        const auto subtable(associate(car(keyList),cdr(localTable),isSameKey));
        if(!isNull(subtable)){
            const auto record(associate(cadr(keyList),cdr(subtable),isSameKey));
            if(!isNull(record)){setfCdr(record,makeList(value));}
            else{setfCdr(subtable,cons(cons(cadr(keyList),value),cdr(subtable)));}
        }else{
            setfCdr(localTable,cons(makeList(car(keyList),cons(cadr(keyList),value)),cdr(localTable)));
        }
        return(makeLeaf("insert"));
    };
   
    const function<string(void)> getTableString
        =[localTable](void){return(listString(localTable));};

   

    const Table dispatch
        =[localTable,lookup,insertf,getTableString](const List& message){
        if(isEq(message,makeLeaf("lookup-proc")))
            {return
             (makeLeaf
              (function<List(List)>
               ([lookup,localTable](const List& keyList){
                   return(lookup(keyList,localTable));})));
            }
        if(isEq(message,makeLeaf("insert-proc!")))
            {return(makeLeaf(insertf));}
        if(isEq(message,makeLeaf("table-string")))
            {return(makeLeaf(getTableString));}
        cerr<<"Unknown operation --- TABLE"<<endl;
        exit(1);
        return(makeList());
    };

    return(dispatch);

}


const Table makeTable(const function<bool(List,List)>& isSameKey)
{return(makeTableDispatch(makeList("*table*"),isSameKey));}

//---------abstraction barrier---------

const Table operationTable
(makeTable(function<bool(List,List)>(isEqual<List>)));

const List get(const List& keyList)
{
    return(executable<List,List>
           (operationTable(makeLeaf("lookup-proc")))(keyList));
}
const List put(const List& keyList, const List& value)
{
    return(executable<List,List,List>
           (operationTable(makeLeaf("insert-proc!")))
           (keyList, value));
}
const string getTableString(void)
{
    return(executable<string>
           (operationTable(makeLeaf("table-string")))());
}


//---------abstraction barrier---------
int main(int argc, char** argv)
{
    cout<<"Excersize 3.24:"<<endl;
    put(makeList(makeLeaf("math"),makeLeaf("+")),makeLeaf(43));
    cout<<"(put 'math '+ 43): operation-table="<<getTableString()<<endl;
    put(makeList(makeLeaf("math"),makeLeaf("-")),makeLeaf(45));
    cout<<"(put 'math '- 45): operation-table="<<getTableString()<<endl;
    put(makeList(makeLeaf("math"),makeLeaf("*")),makeLeaf(42));
    cout<<"(put 'math '* 42): operation-table="<<getTableString()<<endl;
    put(makeList(makeLeaf("letters"),makeLeaf("a")),makeLeaf(97));
    cout<<"(put 'letters 'a 97): operation-table="<<getTableString()<<endl;
    put(makeList(makeLeaf("letters"),makeLeaf("b")),makeLeaf(98));
    cout<<"(put 'letters 'b 98): operation-table="<<getTableString()<<endl;

    cout<<"(get 'math '*) = "
        <<listString(get(makeList(makeLeaf("math"),makeLeaf("*"))))<<endl;

    return(0);
}
----
出力
----
Excersize 3.24:
(put 'math '+ 43): operation-table=('*table* ('math ('+ 43)))
(put 'math '- 45): operation-table=('*table* ('math ('- 45) ('+ 43)))
(put 'math '* 42): operation-table=('*table* ('math ('* 42) ('- 45) ('+ 43)))
(put 'letters 'a 97): operation-table=('*table* ('letters ('a 97)) ('math ('* 42) ('- 45) ('+ 43)))
(put 'letters 'b 98): operation-table=('*table* ('letters ('b 98) ('a 97)) ('math ('* 42) ('- 45) ('+ 43)))
(get 'math '*) = 42

0 件のコメント :

コメントを投稿