プログラミングにおけるタイプ
タイプの誕生
変数を宣言する際にタイプを指定しなければならない言語を使った経験があるなら、ほぼ確実に少しの不快感も感じたことだろう。何か言語はわざわざタイプを決めなくても自動で計算してくれて、意味のないように見えるコードを書くことが時間とエネルギーの無駄のように感じるだろう。タイプが存在しなかった時代のプログラミング環境を想像してみよう。
コンピュータが理解するデータは数値でできていて、人間の立場からはその数値が実際に整数を意味するのか、文字列を意味するのかなどは分からなかった。もちろん、コードを書いた人がよく覚えていれば問題ないだろうが、プログラムが高度化し、複数の人の手を経ると何が何だったのか混乱してバグが生じることしかない。文字列を2乗しても何かしらの数値は出るが、このように意味のない文字列が生じる程度は可愛いものだ。このようなバグはすぐに捕まえることができる。しかし、数百、数千行のコードの間で、どの整数がどのポインターと乗算されても、依然として整数の形を取っているなら、一体このバグをどうやって捕まえるのか?プログラムは問題なく見えても、その結果は散らかっているだろう。
常識的にすぐに試みられる対処法は、「コメントを丁寧に書いてわかりやすくすること」だ。たとえば、Aは整数だ、Bは文字列だといったように丁寧に記しておくことだ。次の問題は「このコメントが確実なのか?」ということだ。バグを減らし、生産性を上げるために変数一つ一つにコメントをつけることは良い。開発中に変数の用途が変われば、そのコメントも丁寧に直す細心さがあれば幸運だ。しかし、コメントも人間がするもので、間違いのためにコメントさえ間違っている可能性があるので、変数が正確に何であるかを正確に指定できる文法がある方が良い。
しかし、この考えはどこか懐かしい。そうだ。これがまさにタイプ指定だ。
このように、タイプは変数が何であるかを示すコメント程度の意味だったが、タイプの役割が顕著になり、その上での研究が続いている。
強いタイプと弱いタイプ
弱いタイプは、前述のタイプの概念から大きく変わっていない強いタイプに対する用語である。タイプチェックに問題がなければ、プログラマの意図とは異なっていてもとりあえずコードを実行する1。もちろん、この「プログラマを疑わない態度」は速度を出すが、それによって生じるバグを事前に捕まえ、生産性を上げるために、強いタイプの概念が考え出された。
強いタイプの言語は、タイプチェックに問題がなければプログラムが正しく動くことを保証する。検査が厳しくなるにつれて、いちいちバグが出るとぼやいてはいけない。事前に察知しなかったら、いずれもっと危険で大きなバグとして戻ってくるだろう。タイプチェックが厳しいということは制約であるが、プログラミングでは制約は「制限」よりも「便利」を意味することが多い。タイプシステムが強ければ、「面倒くさくてタイプを全部指定しなければならない」のではなく、「プログラマの事情に合わせて細かい調整ができる」と受け取ることができる。
弱いタイプにも長所と短所があるが、それが特に意図されたものではなく、強いタイプが強いタイプである理由を説明するために、原始的なタイプの概念に名前をつけたと考えても良い。
静的タイプと動的タイプ
静的言語はコンパイル時にタイプチェックを行い、動的言語はコードが実際に実行されるとき、つまりランタイムにタイプチェックを行う。簡単に言えば、静的言語はデータ型が変わらないコンパイラ言語であり、動的タイプはデータ型がその場その場で変わるインタプリタ言語だ。もちろん、コンパイラ言語は些細な修正のたびに一からコンパイルしなければならないため、インタプリタ言語の生産性が高いが、コンパイルが無事に終われば、速度面ではコンパイラ言語が非常に有利だ。
JavaScriptがこの点で悪名高いことで知られている。 ↩︎