型は、うそをつかない説明書

よみもの+手を動かす時間:およそ20分

半年後のあなたは、他人

前のレッスンで、注釈は「呼ぶ側と作る側の約束」だと学びました。今日は同じ注釈を、もうひとつの顔から見ます。読む人間のための説明書という顔です。

プログラムを書いた本人でも、半年たてば中身を忘れます。つまり今日のコードを受け取るのは、いつだって「他人になった未来のあなた」です。その未来のあなたに、こんな関数が届いたとしましょう。

fn keisan(a, b, c) { … }

何を入れればいいのでしょう。a は数か、真偽か——それを知る方法は、本体の を最初から最後まで読むことしかありません。3行なら我慢できても、これが30行なら、関数を呼ぶたびに本体まで読みに帰ることになります。

「コメントを書けばいい」のでは

minilangには # から行末までを読みとばすコメントがあります( でも始められます)。機械は読みとばし、人間だけが読む——説明書を書く場所として、うってつけに見えます。では、コメントつきの関数をひとつ。

③ 評価された値
800

実はこの関数、本体だけが書き直されたあとです。昔は真偽を受け取っていましたが、いまは価格の数を受け取って2割引きを返します。コメントだけが昔のまま——つまり、うそになっています。

動かしてください。値は 800——エラーも警告も、何も出ません。コメントがうそをついても、ことばの世界の誰ひとり止めてくれないのです。

このコメントを信じた半年後のあなたは、真偽を渡して事故にあいます。ずれた説明書は、説明書がないより、たちが悪い——ないなら本体を読むしかないと覚悟できますが、ずれた説明書は読み手を自信たっぷりにまちがえさせるからです。

同じうそを、注釈で書くと

では同じうそを、コメントではなく型注釈の場所に書いてみます。「kakaku は真偽」——内容はさっきとまったく同じです。

型の目(実行する前の検査)

「*」の左には数が来るはずですが、真偽 が来ています。実行する前から、これは分かります——それが型の目です。

評価された値

(型の目が止めたので、実行していません)

型の目が止めました。「* の左には数が来るはずですが、真偽 が来ています。」——注釈は kakaku を真偽だと宣言しているのに、本体は kakaku に 8 を掛けています。説明書と実装がずれたら、ずれたその瞬間に分かるのです。

これがコメントと注釈の分かれ目です。コメントは人間だけが読む文章、注釈は型の目が毎回検査する文章——だから注釈は、うそをついたままではいられません。実際このコースのminilangは、注釈のない引数を型の目が受けつけないほどの徹底ぶりです(さっきの keisan を貼ると「引数「a」の型が書かれていません。」と断られます)。

ひとつ正直に言うと、型の目は「注釈が古い」のか「本体がまちがい」なのかまでは知りません。指させるのは食い違いの事実だけで、どちらへ直すかを決めるのはあなたです。

型は、使い方の要約

うそをつけない説明書は、読む側からは「信じて読める要約」になります。次の関数を動かして、型の目のパネルに出るチップを見てください。

型の目(実行する前の検査)

型のまちがいは、見つかりませんでした。

nebiki関数(数, 真偽) → 数
評価された値
800

nebiki: 関数(数, 真偽) → 数。この一行が読めれば、本体を1文字も読まずに呼び方が分かります——数と真偽を渡せば、数が返る。minilangに true と書くことばはないので、真偽は 1 == 1 のような比較で作って渡します(1 == 2 に変えると、値引きされない 1000 が返ります)。

思い出してください。コース2で他人の書いた評価器を読んだとき、あなたもまず関数の頭——名前と引数の並び——から読み始めたはずです。人がコードを読む順番は、もともと「要約から」なのです。

名前と型は、べつの仕事をする

nebiki(kakaku: 数, kaiin: 真偽) には、説明が二重に入っています。名前は「何のためか」を語ります——値引き、価格、会員。は「何を入れてよいか」を語ります——数、真偽。

くらべてみてください。

fn k(a: 数, b: 真偽) { … } ※ 入れ方は分かるが、何の関数かは謎
fn nebiki(kakaku: 数, kaiin: 真偽) { … } ※ 目的も入れ方も分かる

上の k は型の目を全部通ります。それでも説明書としては落第です——型だけでは目的が分からず、逆に名前だけでは入れ方が保証されません。コース1で学んだ「あだ名」が「何のためか」を、型が「何を入れてよいか」を受け持つ、そういう分担です。

正直な話——型は、意味までは語らない

最後に、型の側の限界もはっきりさせておきます。次の2つの関数のチップを見てください。

型の目(実行する前の検査)

型のまちがいは、見つかりませんでした。

zeikomi関数(数) → 数hanbun関数(数) → 数
評価された値
110

zeikomi: 関数(数) → 数hanbun: 関数(数) → 数——まったく同じ型が並びます。でも片方は税を足し、片方は半分にする。型は「数を入れれば数が出る」までしか語らず、その数が何を意味するかは語らないのです。

だから、名前とコメントの仕事はなくなりません。型が「何を入れて何が出るか」を検査つきで保証し、名前が「何のためか」を伝え、コメントが「なぜそう書いたか」を補う。三人がかりで、ようやく一冊の説明書です。

演習:最悪の説明書に、名前をつけ直す

次の関数は、型注釈だけは正直ですが、説明書としては最悪です。上の実験室に貼って、まず型の目のチップを確かめてください。それから値をいくつか入れて、この関数の意味を突き止め、ふさわしい名前をつけ直してください。

fn f(a: 数, b: 数) { (a + b) / 2 }
f(10, 20)
ヒント1(考え方)

チップは f: 関数(数, 数) → 数——呼び方はもう分かっています。f(10, 20) は 15、f(3, 4) は 3.5。2つの数のあいだの、ちょうどまんなか……

こたえ

2つの数の平均です。たとえば fn heikin(a: 数, b: 数) { (a + b) / 2 } と直せます。名前を変えても、チップは 関数(数, 数) → 数 のまま——入れ方を保証するのが型の仕事、意味を背負うのが名前の仕事だと、ここでも確かめられます。

このレッスンで分かったこと

  • 注釈のない関数は、本体を全部読まないと使えない——半年後のあなたは他人
  • コメントは人間だけが読む説明書。うそをついても、誰も止めない
  • 型注釈は検査される説明書。実装とずれたら、ずれた瞬間に型の目が止める
  • 型は使い方の要約。本体を読まずに 関数(数, 真偽) → 数 から呼び方が分かる
  • ただし型は意味までは語らない——型・名前・コメントの三人がかりで説明書になる