ソウルフル小話: 型付き関数型言語と C++ は同時に使ってはいけない
いやまじで使っちゃいけないです。
三年前こういうことがあったんです。 Haskell と C++ を使っているコードなんですが、
- 突然ビルドができなくなる。さっきまで上手く行っていたのに、意味不明な C++ のエラーがゴボゴボ出てくる。 git status や hg status してもそんなとこ何も触ってない。そもそも C++ なんか触ってねえし、俺触ってたの Haskell だし!
- make clean してフルビルドしなおすと…やはり C++ のエラー。ふんぎーーーーー!!!
ビルドできたはずのコードに戻して make clean してもビルドエラーが出るわけ。まさに「何もいじってないのに壊れましたぁ」状態。ほら、さすがにプロだから、この台詞は絶対言いたくないんだけど、この台詞でしか説明できない。そのビルドディレクトリをあきらめて別のディレクトリに git clone / hg clone しなおすと…ビルドできる。わけわかんない。
で、昨日ね、まさにそういう同僚がいて私に助けを求めましたですよ。「ちょっとわかんねーなー、これは三年位前俺もひっかかって…あきらめた」とか話しながら見ていたんですが、ビルドルートディレクトリで ls すると、なんか変なファイルがあるわけ
$ ls [String] .... Map Maybe ... String
あれーこれは Haskell の型の名前ですやん。なんでこんなものが…
そこであなたも経験ある型付きの関数型言語プログラマなら必ずやったことがあるはずだと思いますが、型名をコピペしますよな?んで間違って shell にペーストして実行しちゃったことありますよな?
$ Int -> [String] bash: Int: command not found
したら [String] とかいう空ファイルができてしまいますやん。あーそういうファイルだなやーと思ったし、当然中身空だし、消したの。
したらビルドの問題が綺麗さっぱりなくなった。なんでーーー!
C++ の STL のヘッダファイルって拡張子なくって string とか list とかなんですねーひどいね!ビルドルートディレクトリを基点に C++ コードをコンパイルしようとすると、どっかで STL の include があって、
#include <string> #include <list>
とか書いてある。書いてあったらどうなる?ビルドルートに string とか list とかのファイルがあったら読みに行っちゃうんだね!そんなこたぁ起こらない?いや上で見たとおり型付き関数型言語使ってると起こす人いるんだねぇ。んでそれって空のファイルだから、そこではエラーでない訳よ。(変なごみの入ったファイルだったらビルド時のエラーメッセージですぐわかるんだけどね。)後のほーで、多分 STL まわりの意味不明なエラーがゴンゴン出る。え? String だから #include
結論:型付きの関数型言語と C++ を組み合わせて開発をしてはいけない。
ってか STL 作った人って頭悪い。おわり。
ちょっと考えた
ビルドルートがなんでインクルードパスに入ってんねんと思ったが、 ROOT/A/B/B.h とかが山ほどあるので、 #include とかのために入ってないと困る。必須。
やっぱり拡張子無しのヘッダファイルなんか作るやつが悪いってことで終わり。