Rosetta Lisp in Go
GoはGoogleの腕力を感じられる言語である。コンパイルが爆速で、デフォルトでstaticなシングルバイナリを吐く。これはlibcにすら依存しておらず、僕らが理想とするものを1から作った、という感じがする。staticなシングルバイナリとしてはバイナリサイズも手頃だろう。言語自体も実にGoogleらしいというか、命名規則でpublic/privateが決まったり、ファイル名やディレクトリ名でテストコードやプラットフォーム依存コードが決まったりする (golispでは使ってないけど)。
golispの実装上は、何よりジェネリクスが無いのがキツイ。ocalispではSECDマシンのS, C, Dレジスタをそのままリストで表現していたが、Goの container/list の要素型 interface{} はあまりにも... (勿論リストによる表現もパフォーマンスが出る形ではないが) golispでは結局スライスで表現したので、他の言語のLisp実装と比べて継続の利用の相対的なコストが大きい。
エラーハンドリングは if err != nil { .. } チェインするのはしんどいので割り切って recover() している。ジェネリクスとエラーハンドリングはGo 2で真っ先に検討されている項目なので期待。
Goはなんというか愚直に書くべしという感じで、読めばおおよそ動きがわかるようなコードになるが、ジェネリクスがないことを差し引いてもボイラープレートは多い。あとはアンセーフである。 err に限らず nil チェックが静的に検査されないのは厳しい。また、多値の宣言時に err に再代入させようとしたらshadowingが働いて err が nil のまま...とか (linterが教えてはくれる)。
パーサやgoyaccで、レキサは手書きのレキサで済ませた。パーサコンビネータの類はあまりないようだ (当時)。
低レイヤー寄りで、例えばポインタがありつつも、適当に参照を取るとエスケープ解析によって自動でヒープに載ったり、といった塩梅のデザインは面白い。
ocalispの実装は関数型言語の特徴に寄った実装をしていたので翻訳が大変かと思っていたが、全体としては思ったほど書きづらくはなかった。Type switchを多用しているのでこのあたりでパフォーマンスがどうなのかは気になるところ。goroutineは全然試せていないのでまた次の機会に。