で。
言語について。極論すればプログラムはデータとそれに対する操作の集まりである。機械語がそうなっているのだからそうなのだ。ただし、操作の手順もデータとして記録されている。
- 最初は機械がデータを実行するだけだった。
- プログラム上のデータや操作に可読な名前を付けた。
- データの種別ごとに扱いを変えるようにした。
- 動的な記憶領域としてスタックが発明された。
- さらに動的な記憶領域としてヒープが発明された。
現代の言語のほぼ全てはここから先が分化したものだ。
- 最初、名前は一つのデータに対応していた。
- 名前がデータの種別を持つようになった。
- 一つの名前が文脈によって異なるデータに対応するようになった。
「名前とは別にデータ自身が種別を持つようになった。」を忘れていた。
2と3はどちらが先か自信がないが、名前とデータの対応関係の高度化についてはこんなものだろう。例えば、文脈によって対応関係が変わる、そのルールの一例がスコープや構造体、オブジェクトなどである。
- 最初、操作の手順は記述順そのままだった。
- 条件分岐と無条件分岐が発明された。
- 共通する手順を抽出するようになった。
- 記述順と異なる実行順に変換出来るようになった。
手続きについては4がまだ現在進行中で、これ以上進んでいないように思う。例えば、Haskellの遅延実行やメモ化などは4の一例だろう。
結局のところ、チューリング完全な言語同士は原理的に相互変換が可能なのだから本質的な違いはないとも言える。とは言え再利用可能性を高めたり、実行効率を最適化したりといった言語や実装の進化は利用者の手間を大きく減らしてきた。今後は「記述順と異なる実行順に変換」の進化が中心になるのではないかと思われる。