十六進が読めるようになる

2 本連続の probe が、誰もが 16 進で書く数を 10 進で書いた —— SHA-256 の round 定数と Unicode 幅表 —— lexer が 0xFF を整数ゼロ + xFF という識別子として読んだからだ。それはバグでなく papercut だ: 回避は自明で、プログラムは動く。だが二度躓いた papercut はデータであり、修正は lexer の 1 分岐だ。6 リリースの一日を、全部の中で最小の変更と、papercut がいつ修正に値するかの覚え書きで締める。

merelexerergonomicsmethodlanguage-design

Part はその中で最小の変更で締める。ここで終える意図は、その小ささこそが、到達に 6 リリース かかった理由だ、ということにある。これは papercut についての話だ: いつ無視し、いつ修正に値したか。

同じ石に、二度

papercut はバグではない。プログラムは compile し、走り、正しい答えを出す。ただ途中の何かが無駄に ぎこちない。言語は数の lexer に一つ抱えていた: 0xFF は 16 進整数 255 として読まれなかった。整数 0 の直後に xFF という識別子、と読まれたので、それを使う行は後で「unbound variable: xFF」で 失敗した —— 原因から遠く離れた紛らわしいエラーだ。回避は自明: 手で 10 進に変換して 255 と書く。 だから長いこと誰も直さなかった。誰も 16 進リテラルを打つ理由が無かったからだ。

それからこのまさに Part で 2 本の probe が、立て続けに打った。SHA-256 には仕様書が 16 進で列挙 する 64 個の round 定数があり、それらは 10 進でコードに入った。East Asian Width 表はあらゆる表が 16 進で書く Unicode ブロック境界の列で、それらは 10 進のレンジで入った。両方動いた。両方、あるべき よりソースと照合しにくかった。コードを仕様と比べる読み手が、あらゆる数を頭の中で変換せねばならな かったからだ。1 本の probe が 16 進を 10 進で書くのは肩をすくめる話。2 本連続は測定値だ。一度躓く papercut はノイズ。二度躓く papercut は、両方リファレンスから書き写しながら、言語が本物の種類の プログラムと擦れる場所を教えている。

1 分岐と、その払い

修正は lexer の 1 分岐だ: 0 の後に xX と 16 進数字が続いたら、16 進数字を消費して変換 する。0xFF0Xff はいま普通の整数として lex される —— 新しい型は無く、他の整数リテラルと 同じ backend 別の幅 —— そして 16 進数字の無い裸の 0x はまだ 0 + 識別子 x と読まれるので、 以前動いていたものは何も壊れない。8 進も、2 進も、桁区切りも無い。どれもまだ二度は要求されて いない。目に見える払いは、それを主張した 2 本の probe にまっすぐ戻った: SHA-256 example の 64 個の round 定数と 8 個の初期ハッシュ値はいま 16 進で、公開された仕様と行ごとに一致し、チェックサム ツールの多項式とマスクも 16 進だ —— そして両方まだリファレンスの vector と一致する。それが変更の 論拠の全てだ: 言語がこれらのプログラムを以前は表現できなかった、ではなく、いまはそれらが写された 文書のように読める、だ。

帳簿

一日に 6 リリース、4 本の小さなプログラムから、その形ははっきり述べる価値がある。整数の幅と bitwise 演算子は問いとその答えだった —— 演算子を必要とした probe が、その下の幅問題を先に見つけた。 バイト reader とバイト writer は同じ扉の二つの半分。Mandelbrot レンダラは文書が言語に有利に嘘を ついているのを見つけ、この最後の一本は crypto と Unicode の probe が両方感じた摩擦を直した。全ての 下にあるのは一文だ: backend が 4 つある言語は実のところ、4 つの実装に同じ物語を語らせ続ける約束 であり、物語が分岐する場所を見つける最も安い方法は、まさにその一点に届く小さな本物のプログラムを 書くことだ —— ハッシュ、チェックサム、絵、テーブル —— そして各 backend が返す答えを読む。probe は 安かった。それらが比べた真実は安くなかった。方法が次にどこへ行くかは、いつものように、まだ決まって いない —— それこそが要点だ。

← Back to Mere: 言語を作る