型は、うそをつかない説明書
半年後のあなたは、他人
前のレッスンで、注釈は「呼ぶ側と作る側の約束」だと学びました。今日は同じ注釈を、もうひとつの顔から見ます。読む人間のための説明書という顔です。
プログラムを書いた本人でも、半年たてば中身を忘れます。つまり今日のコードを受け取るのは、いつだって「他人になった未来のあなた」です。その未来のあなたに、こんな関数が届いたとしましょう。
fn keisan(a, b, c) { … }何を入れればいいのでしょう。a は数か、真偽か——それを知る方法は、本体の … を最初から最後まで読むことしかありません。3行なら我慢できても、これが30行なら、関数を呼ぶたびに本体まで読みに帰ることになります。
「コメントを書けばいい」のでは
minilangには # から行末までを読みとばすコメントがあります(※ でも始められます)。機械は読みとばし、人間だけが読む——説明書を書く場所として、うってつけに見えます。では、コメントつきの関数をひとつ。
実はこの関数、本体だけが書き直されたあとです。昔は真偽を受け取っていましたが、いまは価格の数を受け取って2割引きを返します。コメントだけが昔のまま——つまり、うそになっています。
動かしてください。値は 800——エラーも警告も、何も出ません。コメントがうそをついても、ことばの世界の誰ひとり止めてくれないのです。
このコメントを信じた半年後のあなたは、真偽を渡して事故にあいます。ずれた説明書は、説明書がないより、たちが悪い——ないなら本体を読むしかないと覚悟できますが、ずれた説明書は読み手を自信たっぷりにまちがえさせるからです。
同じうそを、注釈で書くと
では同じうそを、コメントではなく型注釈の場所に書いてみます。「kakaku は真偽」——内容はさっきとまったく同じです。
「*」の左には数が来るはずですが、真偽 が来ています。実行する前から、これは分かります——それが型の目です。
(型の目が止めたので、実行していません)
型の目が止めました。「* の左には数が来るはずですが、真偽 が来ています。」——注釈は kakaku を真偽だと宣言しているのに、本体は kakaku に 8 を掛けています。説明書と実装がずれたら、ずれたその瞬間に分かるのです。
これがコメントと注釈の分かれ目です。コメントは人間だけが読む文章、注釈は型の目が毎回検査する文章——だから注釈は、うそをついたままではいられません。実際このコースのminilangは、注釈のない引数を型の目が受けつけないほどの徹底ぶりです(さっきの keisan を貼ると「引数「a」の型が書かれていません。」と断られます)。
ひとつ正直に言うと、型の目は「注釈が古い」のか「本体がまちがい」なのかまでは知りません。指させるのは食い違いの事実だけで、どちらへ直すかを決めるのはあなたです。
型は、使い方の要約
うそをつけない説明書は、読む側からは「信じて読める要約」になります。次の関数を動かして、型の目のパネルに出るチップを見てください。
型のまちがいは、見つかりませんでした。
nebiki関数(数, 真偽) → 数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関数(数) → 数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 } と直せます。名前を変えても、チップは 関数(数, 数) → 数 のまま——入れ方を保証するのが型の仕事、意味を背負うのが名前の仕事だと、ここでも確かめられます。
このレッスンで分かったこと
- 注釈のない関数は、本体を全部読まないと使えない——半年後のあなたは他人
- コメントは人間だけが読む説明書。うそをついても、誰も止めない
- 型注釈は検査される説明書。実装とずれたら、ずれた瞬間に型の目が止める
- 型は使い方の要約。本体を読まずに
関数(数, 真偽) → 数から呼び方が分かる - ただし型は意味までは語らない——型・名前・コメントの三人がかりで説明書になる