top page > computer > haskell > web_lecture > for_programmer > paradigm_history.html
更新日:
文責: 重城良国

プログラミングパラダイムの歴史

手続き型から関数型へのパラダイムの遷移を「状態変化との戦い」という軸で見ていく。

(注1): 関数型言語における「関数」とその他の言語における「関数」とは重なるところと大きく異なるところとがある。前者を「関数」と呼び後者を「サブルーチン」と呼ぶことにする。(注2): 「関数型」という概念に含まれる性質のうち「参照透過性」を取り上げている。関数型言語の魅力はほかにもたくさんある。

配線の組み換え

世界初とされることのあるコンピュータENIACは1946年に発表された。コンピュータへの命令は配線の組み換えによってプログラムされた。

機械語

1949年に「プログラム内蔵方式」つまりノイマン型コンピュータのEDSACが作成された。コンピュータに対して配線を組み換えることなく命令を入力できる。それぞれの動作は数値で指定される。入力は穴のあいた紙テープによって行われた。現在のコンピュータも本質的にはこの時代のコンピュータと同じだ。数値化された命令を受け指定された動作を行う。

[EDSACの機械語命令の図]

アセンブラ

機械に対する命令は数値として人間が指定していた。「足し算は何番」「引き算は何番」のように人間が記憶する必要があった。「add eax, 4(レジスタeaxに4を足す)」のような人間に理解しやすい記述を数字の列に変換するほうが書くのも読むのも簡単だ。そのための変換ルールが作成された。機械語への翻訳は人間の役目だった。機械を動かすのにかかるコストが低くなり人間にかかるコストが相対的に高くなってくると変換は機械の役目になった。

構造化プログラミング

機械の動作を反映して実行するコード行に次々にジャンプするというやりかたでコードは組まれてきた。このやりかたには、どのコードがいつ実行されるのかが人間にとって明らかでなく、コードの動作がわかりにくいという問題がある。人間が読みやすいコードの作成のためにはジャンプ命令に対する制限が必要だ。そこで「制限なしのジャンプ」で実現できるアルゴリズムをすべて表現可能で、より扱いやすい3つの組が考えられた。「順接」「反復」「分岐」だ。コードの任意の個所へのジャンプの代わりに、「コードを順に実行」「条件を満たすあいだくりかえす」「条件によって処理を選ぶ」の3つのみを許す。

[構造化の3組のアイコン]

この制限でいつどのコードを実行するかがわかりやすくなる。

サブルーチン

「構造化プログラミング」と並行してサブルーチンという考えかたも生まれた。一連のコードに名前をつけ本流となる処理のなかで呼び出す。引数として与える値を変えることで処理を変化させる。処理の結果何が起きたかは返り値で示すことができる。

変数のスコープ

構造化プログラミングやサブルーチンによってどのコードがいつ実行されるかはわかりやすくなった。データに関する問題がまだ残っている。サブルーチンはデータを変化させる。1つのサブルーチンで完結しない処理Aがあるとする。処理AはA1、A2の2つのサブルーチンから成る。サブルーチンA1が値aを保存する。それをサブルーチンBが値bに変化させる。サブルーチンA2は値aではなく値bで処理を進めてしまう。

[サブルーチンの競合の図]

それぞれのコードが変更できる値を制限しなければならない。「変数のスコープ」という考えかただ。「自分だけが変更できる変数」を使えば他のサブルーチンによる誤った変更はない。C言語で言えばstaticをつけたローカル変数である。「状態変化」をそれぞれのサブルーチンのなかに閉じ込めた。この場合「サブルーチンが状態を持つ」ということになる。

オブジェクト志向

これで他のサブルーチンがデータを書き変えることはない。しかし、1つのサブルーチンが同時に複数のデータを扱うことはできない。トークンの切り出しをするサブルーチンを考えよう。サブルーチンに文字列を読み込み呼び出しのたびにひとつずつトークンを切り出す。サブルーチンの状態が次々と変化する。扱う文字列がひとつのときには問題ない。同時に複数の文字列を扱おうとしたときに破綻する。「状態を持つサブルーチン」を複数用意することで解決できる。文字列Sのトークン切り出しにはサブルーチンAを使い文字列Tのトークン切り出しにはサブルーチンA'を使う。

データごとに「状態を持つサブルーチン」を用意するのがオブジェクト志向の本質だ。

関数型

単純な手続き型からオブジェクト志向へのパラダイムシフトは大きな進展だ。状態変化をオブジェクトという小部屋のなかに閉じ込めて破壊力を減少させた。しかし、本質的な解決ではない。メソッドを呼び出すといろいろな場所で状態が変化する。変化の広がりはメソッドの外からは明らかでない。メソッドはブラックボックスとしては扱えない。内部の動作を知らなければ安全に使えない。サブルーチンのなかでは2つの概念が混ざり合っている。サブルーチンは引数から返り値を生成すると同時に機械の状態を変化させる。前者は関数であり後者は入出力だ。足し算は関数だ。1と2という数と3という数とを関連づける。ファイルの内容を書き換えるのは入出力だ。「純粋な」関数型言語はこの2つを切り分けた。関数は関数であり入出力は入出力だ。サブルーチンというキメラはもはやない。

[ブラックボックスの図]

関数を呼ぶのは安全だ。引数と返り値だけで関数のすることはすべてわかる。関数はブラックボックスとして使える。

まとめ

手続き型、オブジェクト志向、関数型というパラダイムシフトを見てきた。状態変化との戦いである。関数型というパラダイムで「関数」と「状態変化」は切り分けられた。

「1から学ぶHaskell」トップへもどる 「Haskellを学ぶ動機」へ

正当なCSSです! HTML5 Powered with CSS3 / styling, and Semantics