select は要らなかった

古典的な並行ツールキットには、この言語に無い有名な primitive が一つある: 複数の channel を同時に待つこと。pub/sub broker —— 考えうる最もマルチソースなプログラム —— が壁を探しに行った。壁は無かった: broker が反応する全ては variant 型として一つの inbox に漏斗できる。actor パターンだ。言語は必要な部品を全部持っていた。dogfood が代わりに見つけたのは、2 つの機能が出会う場所に隠れていた本物のコンパイラバグ: 再帰ループが呼ぶ helper のネスト関数が helper の局所を閉じ込めるとき、その局所がループのキャプチャに漏れていた。

mereconcurrencychannelscodegenlanguage-design

shutdown、timeout —— 「終わり」のツールキットは 3 分の 2 が古典どおり揃った。3 つ目の古典は select だ: 複数の channel を同時に待ち、先に値を出した方を取る。Go は構文として持ち、 たいていの channel ライブラリは何らかの形で生やす。自然な想定は「この言語にも要る、まだ forcing されていないだけ」だった。だからこの probe はそれを強制しに行った。手持ちで最も マルチソースなプログラム —— pub/sub broker —— で。片側に publishers、反対側に subscribers、 真ん中の broker は購読要求・発行メッセージ・shutdown 信号に反応する —— 3 種の入力、 見かけ上 3 本の channel、見かけ上その上の select

漏斗

壁は来なかった。broker は 3 本の channel を待つ必要が無い。3 種の入力が 3 本の channel で あることを強制するものが何も無いからだ: それらは一つの variant 型の 3 つのコンストラクタ —— PubSubStop —— として単一の inbox を流れ、broker はちょうど一つの受信をブロックして コンストラクタで分岐すればいい。これが actor パターンで、言語は必要な部品を全部持っていると 判明した: variant はタプル payload を channel 越しに運べ、そして —— 本当に自明でなかった部分 —— channel 自身がメッセージの中に乗れる。Sub コマンドは購読者自身の配送 channel を inbox 経由で 運ぶ。channel は第一級のメッセージ payload だ。一般の逃げ道も述べる価値がある: 自分が制御する ソース群への select もどきは一つの inbox への漏斗になり、制御しないソースにはソース毎に forwarder スレッドを立てて一本に merge する。便利さは便利さのままだ。これはこの Part の 2 つ目の 正直な negative result で、「mono が dictionary」の系譜にある: 欠けていた機能は既存のもので 包摂されると判明し、機能を建てる代わりに発見を記録する。

dogfood が実際に捕まえたもの

とはいえ dogfood は手ぶらでは帰らない —— これは 2 つの機能が出会う場所の本物のコンパイラバグを 捕まえた。broker の fan-out helper は自身のネストした再帰関数を含み、それが helper の局所を 閉じ込める。broker のメインループはその helper を呼ぶ。C backend の closure-lifting パスでは、 fixpoint が callee のキャプチャ変数を caller に通す —— 一般には必要だが、それは helper の キャプチャを、その名前が helper 自身の中で束縛済みかを確認せずにループへ足していた。ループの emit された署名は、そのスコープのどこにも存在しない 2 つのパラメータ hnhv を生やした: 「use of undeclared identifier」、原因から抽象 2 層離れたコンパイルエラーだ。修正は fixpoint の skip 条件一つ —— caller 自身の body 内で束縛される callee キャプチャは既にスコープ内にあり、 通してはならない —— と、channel 不要の 20 行に蒸留した回帰テスト。broker はいま 2 topic と 2 subscriber を両 native backend で正しい合計まで走らせる。アークの「終わり」ツールキットは こう立った: close、timeout、close によるキャンセル —— そして意図して select 無し。この Part に 残る一話は、逆向きの攻めをする: 古典プログラム 4 本を一度に言語へ投げ、まだ何か転ぶかを見る。

← Back to Mere: 言語を作る