階層構造と問題2.24~2.28
いよいよ木―Schemeではリストのリスト―が登場。
C++11側で対応する、tupleを要素に持つtupleは、
データ構造としてはすでに表現できているが、表示系listStringが対応していない。
tupleの要素にtupleがあったら、listStringを再帰呼び出しする必要があるが、
そのためにはまずtupleをtupleと認識しないといけない。
これは新ヘッダtype_traitsのis_compoundとかで出来るかと思ったら、
実行時の分岐ではダメだということが判明。
tupleの場合とtupleでない場合の分岐処理を実行時分岐のifで書くと、
tupleに対しては出来ない処理への分岐もコンパイラが評価しに行って、
「tupleではそれはできましぇ~ん」ってコンパイラに泣かれちゃうのね。
ifが問題1.6でいう意味での特殊形式になってない。
C++02までは関数内の変数の型は一度決まれば変わらなかったから、
ifの両方の分岐が評価できたが、型による分岐ではそうはいかないってことだ。
コンパイル時の分岐が必要になる。
まあこれはたぶん、C++11がというより現段階のgccの実装上の問題なのだろう。
でなければis_compoundとかの実行時型識別の存在意義がないし。
それともis_compoundとかはテンプレートパラメターのために使うのかな。
とにかくコンパイルが通らないんじゃしょうがない。
他のSTLコンテナ、例えばunordered_multisetとかで木を表現すると、、
問題によってはばっちりマッチするだろうけど。
SICPで出てくるような、いろんな型が混ぜこぜの一般的な木を表現するには、
tupleでないとぐちゃぐちゃになる。
結局テンプレートマッチングでコンパイル時分岐をさせるしかないんだろう。
木構造再帰になったのでまた書き直し。
ここを楽にするには、さらにもう一段、抽象の壁を必要とするみたいだな。
木構造の再帰を抽象化するのはこれからやるから、そのうち見えてくるだろう。
抽象を得るにはまず具体を知らねば。問題2.24~2.28はそんな問題。
pair?にあたるisPairは、コンパイル時分岐を多用しているために、
多分使う機会は殆ど無いが、一応実装。
また、fringeのように、tupleの木から全く別の構造の木を、
しかもその構造が事前に予測できない木をを作るようなのは、
tupleに向いてない。vectorとかに収めた方がいい。
まあテンプレートでゴリゴリ頑張ればfringeが返すtuple型の予測は、
一応できるが、それは単にコードの二重化なので意味ないし。
ただ、tupleを渡しただけでは葉の型がすぐ明らかではない
(tupleのtupleだったりする)から、leafの型を別に渡すようにした。
以前との共通部分を含めると、ソースがだいぶ長くなってきた・・・。
そろそろライブラリにしたほうがいいか。
----
//
pair?
template<typename
TupleArg1,typename... TupleArgs>
constexpr
bool isPair(const tuple<TupleArg1, TupleArgs...>& tupleList)
{
return(true);
}
template<typename
DataType>
constexpr
bool isPair(const DataType& tupleList){
return(false);
}
//print
list and vector to string
template
<typename Tuple1stArg, typename... TupleArgs>
void
listStringElement
(const
tuple<Tuple1stArg, TupleArgs...>& tupleList,
stringstream& listSStream);//prototype
template
<typename LeafType> void listStringElement
(const
LeafType& leaf, stringstream& listSStream);
void
listStringElement
(const
NullTupleType& tupleList,stringstream& listSStream){}
template <typename ...TupleArgs,typename...
TupleTupleArgs>
void
listStringElement
(const
tuple<tuple<TupleTupleArgs...>,TupleArgs...>& tupleList,
stringstream& listSStream)
{
listSStream<<"(";
listStringElement(car(tupleList),listSStream);
listSStream<<")";
if(!isNull(cdr(tupleList))){listSStream<<" ";}
listStringElement(cdr(tupleList),listSStream);
}
template
<typename Tuple1stArg, typename... TupleArgs>
void
listStringElement
(const
tuple<Tuple1stArg,TupleArgs...>& tupleList,
stringstream& listSStream)
{
listStringElement(car(tupleList),listSStream);
if(!isNull(cdr(tupleList))){listSStream<<" ";}
listStringElement(cdr(tupleList),listSStream);
}
template
<typename LeafType> void listStringElement
(const
LeafType& leaf, stringstream& listSStream)
{listSStream<<leaf;}
template
<typename Tuple1stArg, typename... TupleArgs>
const
string listString
(const
tuple<Tuple1stArg,TupleArgs...>& tupleList)
{
stringstream listSStream;
listSStream<<"(";
listStringElement(tupleList,listSStream);
listSStream<<")";
return(listSStream.str());
}
template
<typename Argument>
const
string listString(const vector<Argument> vectorList)
{
stringstream listSStream("");
listSStream<<"(";
if(vectorList.size()>0){
for_each(vectorList.begin(),vectorList.end(),
[&listSStream](const Argument& arg)
{listSStream<<arg<<"
";});
}
string tmpString(listSStream.str());
tmpString[tmpString.size()-1]=')';
return(tmpString);
}
template
<typename LeafType>
const
string listString(const LeafType& leaf)
{
stringstream listSStream;
listSStream<<leaf;
return(listSStream.str());
}
//
count-leaves
const
int countLeaves(const NullTupleType& x){return(0);}
template<typename
LeafType>
const
int countLeaves(const LeafType& leaf){return(1);}
template<typename
TupleArg1, typename... TupleArgs>
const
int countLeaves(const tuple<TupleArg1,TupleArgs...>& x)
{return(countLeaves(car(x))+countLeaves(cdr(x)));}
//
deep-reverse
const
NullTupleType deepReverse(const NullTupleType& null)
{return(null);}
template<typename
LeafType>
const
LeafType deepReverse(const LeafType& leaf){return(leaf);}
template<typename
TupleArg1,typename... TupleArgs>
const
tuple<TupleArg1,TupleArgs...>
deepReverse(const
tuple<TupleArg1,TupleArgs...>& tupleList)
{
return(append(deepReverse(cdr(tupleList)),
makeList(deepReverse(car(tupleList)))));
}
//fringe
template<typename
LeafType>
void
fringeVectorize(const NullTupleType& null,
vector<LeafType>& leafList){}
template<typename
LeafType>
void
fringeVectorize (const LeafType& leaf,
vector<LeafType>& leafList)
{leafList.push_back(leaf);}
template<typename
TupleArg1,typename... TupleArgs,typename LeafType>
void
fringeVectorize(const tuple<TupleArg1,TupleArgs...>& tupleList,
vector<LeafType>& leafList)
{
fringeVectorize(car(tupleList),leafList);
fringeVectorize(cdr(tupleList),leafList);
}
template<typename
TupleArg1,typename... TupleArgs,typename LeafType>
const
vector<LeafType>
fringe(const
tuple<TupleArg1,TupleArgs...>& tupleList, const LeafType leaf)
{
vector<LeafType> leafList(0);
fringeVectorize(tupleList,leafList);
return(leafList);
}
int
main(int argc, char** argv)
{
auto
tree1(cons(makeList(1,2),makeList(3,4)));
cout<<"x="<<listString(tree1)<<endl;
cout<<"(length x) =
"<<length(tree1)<<endl;
cout<<"(count-leaves x) =
"<<countLeaves(tree1)<<endl;
cout<<endl<<"(list x
x)="
<<listString(makeList(tree1,tree1))<<endl;
cout<<"(length (list x x)) =
"
<<length(makeList(tree1,tree1))<<endl;
cout<<"(count-leaves (list x
x)) = "
<<countLeaves(makeList(tree1,tree1))<<endl;
cout<<endl<<"Excersize
2.24:"<<endl;
auto
tree2(makeList(1,makeList(2,makeList(3,4))));
cout<<"(list 1 (list 2 (list 3
4))) = "<<listString(tree2)<<endl;
cout<<endl<<"Excersize
2.25:"<<endl;
auto tree3(makeList(1,3,makeList(5,7),9));
cout<<"x2.25-1 =
"<<listString(tree3)<<endl;
cout<<"(car (cdr (car (cdr (cdr
x25))))) = "
<<listString(car(cdr(car(cdr(cdr(tree3))))))<<endl;
cout<<endl;
auto tree4(makeList(makeList(7)));
cout<<"x2.25-2 =
"<<listString(tree4)<<endl;
cout<<"(car (car x2.25-2))) =
"
<<listString(car(car(tree4)))<<endl;
cout<<endl;
auto tree5(makeList
(1,makeList
(2,makeList
(3,makeList
(4,makeList
(5,makeList(6,7)))))));
cout<<"x2.25-3 =
"<<listString(tree5)<<endl;
cout<<"(car (cdr (car (cdr (car
(cdr (car "
<<"(cdr (car (cdr (car
(cdr(x2.25-3))))))))))))) = "
<<listString(car(cdr
(car(cdr
(car(cdr
(car(cdr
(car(cdr
(car(cdr(tree5)
))))))))))))<<endl;
cout<<endl<<"Excersize
2.26:"<<endl;
auto x226(makeList(1,2,3));
auto y226(makeList(4,5,6));
cout<<"(append x y) =
"<<listString(append(x226,y226))<<endl;
cout<<"(cons x y) =
"<<listString(cons(x226,y226))<<endl;
cout<<"(list x y) =
"<<listString(makeList(x226,y226))<<endl;
cout<<endl<<"Excersize
2.27:"<<endl;
auto
x227(makeList(makeList(1,2),makeList(3,4)));
cout<<"x =
"<<listString(x227)<<endl;
cout<<"(reverse x) =
"<<listString(reverse(x227))<<endl;
cout<<"(deep-reverse x) =
"<<listString(deepReverse(x227))<<endl;
auto
x227_2(makeList(makeList(1,2),makeList(3,4),makeList(5,6)));
cout<<endl<<"x =
"<<listString(x227_2)<<endl;
cout<<"(deep-reverse x) =
"<<listString(deepReverse(x227_2))<<endl;
auto
x227_3(makeList(makeList(1,2,3),makeList(4,5,6),makeList(7,8,9)));
cout<<endl<<"x =
"<<listString(x227_3)<<endl;
cout<<"(deep-reverse x) =
"<<listString(deepReverse(x227_3))<<endl;
cout<<endl<<"Excersize
2.28:"<<endl;
const int leafDummy(0);
cout<<"x =
"<<listString(x227)<<endl;
cout<<"(fringe x) =
"<<listString(fringe(x227,leafDummy))<<endl;
cout<<endl<<"x =
"<<listString(x227_3)<<endl;
cout<<"(fringe x) =
"<<listString(fringe(x227_3,leafDummy))<<endl;
return(0);
}
----
出力
----
x=((1
2) 3 4)
(length
x) = 3
(count-leaves
x) = 4
(list
x x)=(((1 2) 3 4) ((1 2) 3 4))
(length
(list x x)) = 2
(count-leaves
(list x x)) = 8
Excersize
2.24:
(list
1 (list 2 (list 3 4))) = (1 (2 (3 4)))
Excersize
2.25:
x2.25-1
= (1 3 (5 7) 9)
(car
(cdr (car (cdr (cdr x25))))) = 7
x2.25-2
= ((7))
(car
(car x2.25-2))) = 7
x2.25-3
= (1 (2 (3 (4 (5 (6 7))))))
(car
(cdr (car (cdr (car (cdr (car (cdr (car (cdr (car (cdr(x2.25-3))))))))))))) = 7
Excersize
2.26:
(append
x y) = (1 2 3 4 5 6)
(cons
x y) = ((1 2 3) 4 5 6)
(list
x y) = ((1 2 3) (4 5 6))
Excersize
2.27:
x
= ((1 2) (3 4))
(reverse
x) = ((3 4) (1 2))
(deep-reverse
x) = ((4 3) (2 1))
x
= ((1 2) (3 4) (5 6))
(deep-reverse
x) = ((6 5) (4 3) (2 1))
x
= ((1 2 3) (4 5 6) (7 8 9))
(deep-reverse
x) = ((9 8 7) (6 5 4) (3 2 1))
Excersize
2.28:
x
= ((1 2) (3 4))
(fringe
x) = (1 2 3 4)
x
= ((1 2 3) (4 5 6) (7 8 9))
(fringe
x) = (1 2 3 4 5 6 7 8 9)
0 件のコメント :
コメントを投稿