古典四重奏

教科書のプログラム 4 本を一気に言語へ投げた。各々が疑わしい soft spot を狙う: 行列積はネストしたコンテナへ、Game of Life は世代更新へ、数独は書いて戻すバックトラックへ、桁 vector の階乗は固定幅整数へ。4 本とも両 native backend で一発正解、新バグゼロ。probe 駆動の修正 26 リリースの後、何も転ばない一日は空振りの probe ではない —— それは方法全体が目指していた測定であり、他と同じように記録される。

mereexamplesmethodtestinglanguage-design

この連載のこれまでの probe は全て「壊れていそうなもの」を狙い、大半が当たった。Part 最後の この話は賭けを反転する: 古典プログラム 4 本を、各々が最近の仕事で疑わしくなったサブシステムに 寄りかかるという理由で選び、一気に走らせて何が転ぶかを見る。行列積はネストしたコンテナ (Vec[Vec[float]])とその下の copy-on-store 意味論に寄りかかる。Game of Life は「現世代を 読みながら次世代を書く」に。数独は「書いて戻す」に —— 数字を書き、再帰し、undo が本当に undo することを信じねばならないバックトラッキングソルバだ。そして大数の階乗は、整数の物語が明示的に 与えないもの —— 任意精度 —— に、わざと寄りかかる。

4 本、バグゼロ

4 本とも、interpreter と C backend で、初回実行で正解した。行列積は厳密。glider は 4 世代ごとに 斜めへ 1 セル移動し、8 世代後には Conway の言うとおりの場所に、5 セルで残骸なしに座る。9×9 の パズルは既知の唯一解に解ける。そして階乗の段は固定幅の物語を二幕で正直に語る: native の 21! は両 backend で同じ負数へ wrap し —— 同じ wrap が同一に、というのは 2 つ前の Part の幅統一への 小さな勝利でもある —— それから桁の vector から 30! の 33 桁が、最後のゼロまで正しく出てくる。 最もバグがありそうな 4 箇所で、新バグゼロ。26 リリースの発見と修正の後で、これは退屈な結果では ない。方法がずっと指していた測定だ: 言語のテスト済み表面が、教科書の一章分を越えて育った。 四重奏は examples ディレクトリに加わる —— うち 1 本は新しい名前で。Game of Life は構文糖の ショーケースとして既に存在していて、probe で歴史を上書きするのはそれ自体が小さなバグだった だろうから。

唯一の痛みと、Part の帳簿

一つだけ痛んだが、それは意味論でなくメッセージだった。行列コードはセルを小さな多相 helper 越し に読む。型検査器が s + get a i * get b j を見る瞬間、helper の要素型はまだ未解決の変数だ —— だから数値演算子は int に default し、やがて出る「expected float, got int」は本当の原因から 遠い無実の式を指す。defaulting の規則そのものは残る(2 つ前の Part で秤にかけ文書化した)。 変わったのはエラーが自分を説明するようになったことだ —— hint が defaulting を名指し、2 つの 逃げ道を示す: パラメータに注釈するか、片方のオペランドに ascription を付けるか。かくして Part の 帳簿: channel は閉じ方を学び、supervisor は諦め方を学び、select は不要と判明し、capture 解析の バグが pub/sub broker の中で死に、古典 4 本がクリーンに走った。「終わり」のツールキットは 3 本の 小さなプログラムが要求したから存在する。四重奏は土台の残りが持ちこたえていると言う。次の Part が 何を測るかは、いつものように、まだ決まっていない —— probe が選ぶ。

← Back to Mere: 言語を作る