局所表の表現・透過性テストの選択と表の多次元化:問題3.24~問題3.25(3.25は難儀中)
2章で重要な役割を果たしたget,putの、
メッセージパッシング実装。
問題3.24までは問題なし。
だが問題3.25がうまくいかない。
lookupとinsert!が再帰クロージャにならないといけないのだが、
再帰が入ると、クロージャが自分自身への参照をキャプチャして、
かつクロージャの関数オブジェクトを保持し続ける、
ということが出来なければならない。
が、キャプチャするのが関数オブジェクトの参照で、その参照元は、
宣言したところの寿命が尽きると死ぬから、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 件のコメント :
コメントを投稿