docs を直した絵
Mandelbrot レンダラが、docs が約束した税を測りに入った: float の infix 演算子は無い、だから全ての式は prefix 呼び出しの山になる、と。docs は言語に有利な方に間違っていた —— float の infix 算術は 3 backend でしばらく前から動いていて、docs に忠実な読み手は一行につき 9 個の無駄な prefix 呼び出しをただ書いていた。古い一文の周りに本物の gap が 3 つ隠れ、向こう端から出てきた絵は正しく、生ピクセルでも ASCII でもバイト単位で同一だった。
この Part の大半は、言語が見かけより狭かったことについてだ。この話は言語が見かけより広かった 回 —— 文書が実在するより貧しい言語を記述していて、制限を測るために書かれた probe が、制限は静かに 解除されていたと見つけた回だ。
無い税を測る
計画は Mandelbrot レンダラ、まさに float 算術が底まで続くから選んだ。リファレンスが記述する税を
定量化するためだ: float は「prefix 関数形のみ、infix なし」—— 全ての a*b + c はネストした
prefix 呼び出しで書かねばならず、脱出時間の式は膨れ上がる。レンダラのまさに最初の行が負の float
リテラルを欲しがって type error を得て、それは裏付けに感じられた。それから無関係な何かを確認して
いて、1.5 + 2.0 が 3.5 を返した。float の infix + は動いた。-、*、/、そして全ての比較
も —— interpreter で、C で、wasm で。overload はどこかで足され、リファレンスは一度も更新されて
いなかった。まだ prefix-only の世界を約束し、それを信じた読み手は三行の式に理由もなく 9 個の無駄な
prefix 呼び出しを書く。これは前 Part の「既にあった」の話の鏡像だ: あちらでは probe が建てるつもり
の機能が既にあると見つけた。ここでは probe が docs が否定した機能が既にあると見つけた。文書は
両方向にずれうる。そしてどちらにずれたかは、言語を走らせることだけが教える。
本物の gap 3 つと、正直なしわ
古い一文は本物の gap を 3 つ隠していて、全部直した。単項マイナスはまだ整数専用で ——
-2.5 は本当に type error で、負の float リテラルは名前付きの否定関数を要した —— だから二項演算子と
同じく数値 overload になった、4 backend 全部で。LLVM backend は、判明したところでは、float の
infix 算術に対して浮動小数点オペランドに整数加算命令を emit していた —— コンパイラが即座に拒否する
invalid IR で、float 比較には整数比較を —— だから適切な浮動小数点加算一家と ordered な浮動小数点
比較を得た。そして前話のバイナリ物語の書き半分が欠けていた: バイト vector の reader はあったが
writer が無く、だからレンダラは対になる write_file_bytes を得て、画像形式の ASCII 逃げの代わりに
生ピクセル形を emit できるようになった —— 生形は約 3 分の 1 のサイズだ。レンダラは 400×300 の集合を
素の infix 数式で描き、その生ピクセル出力は ASCII 版のピクセルとバイト単位で同一だ。一つの正直な
しわが残り、訂正された docs に書き込まれている: overload はオペランドが具体的に float のときだけ
float に解決するので、注釈なしの関数パラメータはまだ整数に default し、float 中心のコードは
パラメータに注釈する。訂正はリファレンスと標準ライブラリのノートの両方に入った。教訓は Part 全体と
対になる: 4 backend は互いに食い違いうる、そして docs は 4 つ全部と一度に食い違いうる。Part 最後の
話は、これらの probe のうち 2 本が回避せねばならなかった papercut を直し —— そしてその日の帳簿を
閉じる。