順序のもう半分
セルフホストの fixpoint は頂だったが、頂は立ち去る場所だ。降りる最初の一歩は、何 Part も前に声に出して名づけた負債を返すことだった:言語は任意の二値を構造的等価で比べられたが、順序づけはできなかった。それを終える —— 構造的等価の傍らに構造的な less-than を —— ことで、trait システムを一切建てずに育ててきた振る舞いの一家が完成した。しかもそれは、その一家がすでに出来ているまさにその機構を再利用して為された。
頂は目的地でない;振り返って降り始める場所だ。前の Part はその一つで終わった —— bootstrap fixpoint、コンパイラが自分自身を byte 単位で同一の複製にコンパイルする —— そしてこの Part は その向こう側の地面についてだ。そこで仕事は、コンパイラが自分自身について何かを証明することから 離れ、言語が何をでき何をまだできないか、へと戻った。降りる最初の一歩は小さく具体的で、そして ずっと前の Part から、名づけられて待っていた。
声に出して名づけた負債
何 Part も前、導出された振る舞いの一家が建てられたとき —— 値をテキストとして描画する、JSON へ シリアライズして戻す、二値を構造的等価で比べる、すべて trait システムなしにコンパイル時に型ごと 特殊化 —— 一つのメンバが欠けていると平明に述べられた。言語は二値が等しいかをその形を歩いて 問えたが、どちらが小さいかは問えなかった。構造的等価はあり、構造的順序はなかった。後に建てた 数値ツールがその gap に正面からぶつかった:比較を手で綴ることでしか list をソートできなかった、 なぜなら比較演算子は数と文字列には効いても、実のデータセットが出来ている tuple や record には 効かなかったから。縁は開けたまま、隠すのでなく未建として書き留められた —— プロジェクト全体の規律が 「プログラムがその不在を具体的にするまで先送りする」だったから —— そしていま、一つが具体的にした。
一家を、その一家自身の部品から完成させる
心地よいのは、それを終えるのに新しい機構が要らなかったことだ。相棒を欠いていた等価は、trait でも 辞書でも runtime lookup でも実装されていなかった;型検査器が各使用で具体型を知り、コード生成器が その型のための正しい比較を、inline で、コンパイル時に emit することで実装されていた。順序は まさに同じ枠に嵌まる。less-than とその三つの親戚が、いまや任意の具体型で効く:整数と浮動小数点数と 文字列は直接比較し、tuple・record・list・variant は辞書式に比較する —— 成分ごと、宣言順の フィールドごと、要素ごと、そして variant はまず宣言順で、次に中身で。それぞれが型ごとの小さな比較 関数として emit される、すでに emit されていた等価関数の順序版として。一つの名前、多くの型固有の 振る舞い、静的に選ばれる —— 描画と JSON と等価が持っていたのと同じ形、いま比較が完成して。
「小さい」の意味を backend 間で一致させる
唯一の本当に新しい決定は、言語が順序を渡してこない場所でどんな順序を課すか、だった。数と文字列には
明白な順序がある;variant 型にはない。Red | Green | Blue に内在するランキングはないので選択が
要り —— そしてここが肝心 —— interpreter と両コンパイル backend が同じ選択をせねばならない、
さもないと値が interpreter では一方に、native バイナリでは別の順にソートされる。選ばれた順序は
宣言順:最初に書かれた constructor が最小。それは発見でなく選択だが、全順序で決定的で、interpreter は
コード生成器が constructor を番号づけるのと同じソースからそれを再構成するので、三者が byte 単位で
一致する。その一致は、プロジェクト全体がこの種を確かめるやり方で確かめられる —— 同じ値を三通りに
ソートし同一に出ることを要求する —— 主張でなく。
残った縁
一家を完成させても全ては閉じず、正直なのはどの隅が残ったかを言うことだった。型注釈なしに書かれた 比較は operand を整数に default するので、便利な一行ソート —— comparator を全く取らないやつ —— は いまも整数専用だ;それ以外の list をソートするには注釈つきの比較を綴りたくなる。完全に一般な版、 言語が「順序づけ可能」を制約として推論し要素型が落ち着く先で解決する版は、別の、より大きな機械 —— 本物の ad-hoc 多相解決 —— で、以前と同じ規則の後ろに先送りのまま:プログラムがその不在を耐え難く するまで。ship したのは構造的比較そのもので、あらゆる具体型であらゆる backend にわたって効く。 それが価値の大半で、新しい機械はゼロだ。
これは頂から降りる意図して控えめな最初の一歩だった —— 負債を返し、一家を完成させ、前の Part の 約束を開けたまま守った。次に来たものは控えめでなかった。言語がすでに持つものの片づけを終え、仕事は 外へ、まったくできないことへと向いた —— そしてそれらを見つける道は、推測することでなく、何か実の ものを建てたときに痛む場所を探しに行くことだった。