レベル: 初級 まつもとゆきひろ, Writer, ITmedia
2007年 5月 25日 近ごろプログラマーかいわいで、「関数型プログラミング言語」という言葉をよく耳にするようになりました。本連載では、プログラミング言語を取り巻く状況をあらためて俯瞰し、プログラミング言語開発の現場で何が起こっているのかを解説します。
はじめに
「ガーベジコレクション」、「リフレクション」、「アスペクト指向」、「クロージャ」、「イテレータ」、「型推論」など、近年、プログラミング言語の世界に新しい概念が続々となだれ込んでいるように見えます。しかし、これら「プログラミング言語の新潮流」の背景には、実はあまり知られていない歴史が隠されているのです。
プログラミング言語のメインストリーム
プログラミング言語はお互いに影響を与えながら成長しています。プログラミング言語の歴史において、主要な言語がどのように影響を与えたかを、概略図に示しましょう(図1)。この図では非常に簡略化しています*が、実際には数えきれないほどの言語*がさまざまに影響を与え合っています。
図1 プログラミング言語系統図(概略)
王道を行くFortran、COBOL、C/C++、Java、C#
プログラミング言語には、王道とでも呼ぶべき定番のものが連綿と続いてきました(図1 上部)。その中でも「始祖」に当たるのがFortran(Formula Translator)でしょう。1954年生まれのFortranは、史上最初の高級言語として誕生し、また科学技術計算の分野ではいまだに現役で活躍しています。特にベクトルプロセッサを積んだスーパーコンピューティングの領域では、ほかの言語の追随を許しません。また、事務計算用言語として誕生したCOBOL(Common Business Oriented Language)も、まだまだ現役*です。
C言語は、UNIXの主要開発言語として普及しました。現在ではその地位を、C++にかなり明け渡しつつありますが、それでもなお現役で活躍しています。
あくまでもオブジェクト指向機能を付加したCとして(ほぼ)上位互換を目指すC++に対し、より高級な言語としてSun Microsystemsから華々しく登場したのがJavaです。また、マイクロソフトがJavaへの対抗馬として誕生させたのがC#になります。
軽量で人気を集めるスクリプト言語
一方、1987年のPerlの登場以来、スクリプト言語と呼ばれる分野が発展してきました。もともとスクリプト言語は、システムをプログラムできるようにするための言語として登場しました。例えば「チャットスクリプト」は、モデムを経由してネット接続する場合に、先方の対応(プロンプトなど)に応じて適切な出力を行いログインを行うもので、スクリプトの典型です。また、コマンドラインでの繰り返しを自動化するための「シェルスクリプト」などが、初期のスクリプト言語の対象でした。
当初のスクリプト言語は、機能の少ない簡易言語という雰囲気でしたが、Perlが登場したことで、一般的なプログラミングにも使える機能を備え、プログラミング言語の新しい領域が切り開かれました。多くのスクリプト言語はテキスト処理能力に優れているのですが、この特質はテキスト主体のプロトコルであるHTTPとも相性が良好です。Perl、PHP、Pythonなどのスクリプト言語は「P言語*」と呼ばれ、Webアプリケーション開発言語として注目されています。
一風変わっているのがJavaScriptです。1995年にリリースされたNetscapeブラウザに組み込まれていたこの言語は、もともとLiveScriptという名前で開発されていましたが、Javaの人気にあやかるべくJavaScriptと改名されました。やや文法が似ているものの、名前が連想させるほどにはJavaとの直接の関係はありません。Ajaxの流行もあり、「世界で一番ユーザーの多い言語」*として定着しつつあります。
知られざる言語たち
図1の下半分、点線より下の部分には、あまり有名でない言語が並んでいます。幾つかは名前くらい聞いたことがあるかもしれません。これらの言語は主にアカデミックな領域(大学や企業の研究機関など)で使われることが多く、図1の上半分に登場する言語ほど、たくさんのユーザーを獲得することはありませんでした。しかし、学術分野で研究し使われてきた言語の中には、強力な機能を持つものがたくさんありました。実は「プログラミング言語の新潮流」とは、これら「知られざる言語」たちの機能がメインストリームの言語に取り込まれているという流れなのです。それらの言語の幾つかを紹介してみようと思います。
数学的記法をコンピュータで実行可能にしたLisp
Lispのことを知られざる言語などと呼んでしまうと、怒り出す人もいるかもしれません。LispはFortranに続くくらい古い言語であり、また人工知能をはじめとする、さまざまな研究分野で非常に広く活用されてきました。趣味のプログラミングや商業プログラムの領域ではそれほど有名ではありませんが、それでもEmacsやAutoCADのカスタマイズ言語として、あるいは「クラッシュ・バンデクー」のゲーム記述言語などとして、Lisp系言語はいろいろなところで密かに活躍しています。Lispの簡単なサンプルプログラムをリスト1に示します。
リスト1 Lispのサンプルプログラム(階乗を計算する)
(defun fact (n)
(if (= n 0)
1
(* n (fact (1- n)))))
|
古典的言語の代表格であるFortranが、正直なところ古臭い印象を与えてしまうのに対して、ほぼ同じくらい古いはずのLispにはそのような印象がありません。むしろ、見かけは変わっているものの、つぎつぎと新しいアイデアを生み出しています。プログラミング言語の新潮流と見なされる新しい概念の多くも、実はずっと昔にLispで発明されたものが多いのです。
- Lispの特徴 Lispは、1958年にMITのジョン・マッカーシー(John McCarthy)によって「発見」されました。当初、Lispはアルゴリズムの表現方法として考え出されたものです。Fortranをはじめとするほかのプログラミング言語が、あくまでもコンピュータに処理手順を伝達するための記法として誕生したのに対して、Lispは数学的記法をコンピュータで実行可能にしたという違いがあります。FortranとLispの最大の違いは、このような誕生のいきさつにあると言えるでしょう。 Lispには、次のような非常にユニークな特徴が備わっていました。
- 基礎部分が非常にシンプル
- LispでLispを記述するのが簡単
- プログラムそのものをデータとして操作できる
これらの特徴は、要するに現代で言うリフレクション機能を備えていることを意味しています。これによってLispは、目的に合わせて言語自身をどんどん拡張できる柔軟性を備えていました。学術分野ではこのような性質が非常に好ましかったので、Lispはアカデミックな領域で広く使われ、人工知能などのいろいろな研究分野で活用されたのです。 しかし、あちこちの大学や研究所でLispが使われるようになって、だんだん困った事態も発生してきました。すでに述べたように、Lispはコアがシンプルで簡単に実装できる上、言語拡張も簡単です。そのため、あちこちにLispの方言が生まれてしまって、「せっかく開発したLispプログラムが、よそのLisp処理系では動かない」という事態が頻発するようになったのです。
- Lispの最小公倍数的な存在を目指したCommon Lisp これを受けて2つの動きが生まれました。1つは、世の中に存在するあらゆるLispの最小公倍数的な存在を目指したCommon Lispです。実際には、互いに矛盾する部分の解消があったり、既存のものとはまったく違う新しいアイデアを盛り込んだりしたので、厳密には最小公倍数ではないのですが、とにかく古今東西のあらゆるLispプログラムを移植するのに必要そうな機能を盛り込んだ巨大なLisp仕様です。Common Lispは最終的に、ANSI規格として策定されています。
- 限りなくシンプルで切れ味の鋭いLisp言語を目指すScheme もう1つの動きは、長い歴史の中でLispが抱え込んできたいろいろなものをすべてそぎ落として、限りなくシンプルで切れ味の鋭いLisp言語を定義しようというものです。このLispはSchemeと呼ばれました。現在Lispと言えば、そのほとんどがCommon LispかSchemeのいずれかを意味します*。 後述しますが、Lispから生まれた概念はたくさんあります。それはLispが、長年その柔軟性によって「言語機能の実験場」としての役割を果たしてきたことと、学術分野の頭のいい人たちが、研究成果として、あるいは自分たちがラクをするために精進してきたことの結果です。
子供たちが使える言語を目指したSmalltalk
Smalltalkは、1970年代にダイナブック構想を実現させるためのプログラミング言語として開発が始まりました。ダイナブック構想とは、アラン・ケイ(Alan Kay)らが計画した「子供たちにコンピューティングパワーを」というプロジェクトです。初期のSmalltalkはBASICで書かれた小さなプログラムとして始まったそうですが、最終的にはLispの影響を強く受けた*言語になりました。アラン・ケイは、「子供たちから離れてしまった」と不満を覚えていたそうですが。
Smalltalkはオブジェクト指向という考え方を世に広めた言語としても知られています。子供たちがプログラムの構造を理解しやすくするために導入された考え方ですが、その後多くの言語に影響を与え、現在ではオブジェクト指向機能を持たない言語の方が少数派になってしまいました。
しかし、オブジェクト指向という概念そのものは、Smalltalkによって発明されたものではありません。その概念は、1960年代後半スウェーデンのクリステン・ニガルド(Kristen Nygaard)らによってSimula言語に導入されたものです。当時は「オブジェクト指向」という単語はまだありませんでしたが、クラスや継承などオブジェクト指向プログラミングにとって重要なアイデアはSimulaにおいてすでに実現されていました。
ビアルネ・ストラウストラップ(Bjarne Stroustrup)によるC++は、オブジェクト指向という考えをSmalltalk経由ではなく、Simulaから直接導入しています。以前お会いしたときに直接聞いたところによると、ストラウストラップは大学院時代にSimulaのユーザーであったため、その機能をC言語に取り込みたかったというのが、C++の直接の開発動機だったそうです。
数学的な関数を意識して最も早く実用レベルに到達したML
ML(Meta Language)はLispほど有名ではない言語です。もともとはEdinburgh大学のロビン・ミルナー(Robin Milner)らによって開発されたEdinburgh LCF(Logic for Computable Function)定理証明システムの推論規則を記述する言語として設計されました。MLは関数をベースにしたプログラミング言語なので、関数型プログラミング言語と呼ばれます。MLの簡単なサンプルプログラムをリスト2に示します。
リスト2 MLのサンプルプログラム(階乗を計算する)
fun fact 0 = 1
| fact n = n * fact(n-1);
|
MLは最古の関数型プログラミング言語ではありませんし、最高の関数型プログラミング言語でもありません。最古の関数型プログラミング言語は、(おそらく)ジョン・バッカス(John Backus)*が作ったFPでしょうし、また長らくLispも関数型プログラミング言語*と呼ばれてきました。しかし、「数学的な関数を意識したプログラミング言語」のうち、最も早く実用レベルに到達したのがMLであることは間違いないでしょう。一方、後で紹介するHaskellなどと異なり、MLは副作用を完全に排除していないので「純粋でない」関数型言語と呼ばれることもあります。
MLの最大の特徴は、やはりその型システムでしょう。MLはすべての変数や式が厳密な型を持つ静的型の言語です。しかし、型推論システムが組み込まれているので、ユーザーはほとんど型を明示的に指定する必要がありません。例えばリスト2のプログラムでは、「factという関数は整数を引数に取り、整数を返す」と型推論システムが自動的に判定してくれています。また、関数実行時にパターンマッチが発生するのも特徴です。リスト2では「0のとき、~。それ以外のとき、~」という形で、引数のパターンによって実行される定義を切り替えています。
MLの処理系としては、SML/NJやOCamlが有名です。
純粋関数型言語Haskell
Haskellは純粋関数型言語です。この場合の「純粋」とは、副作用がないことを意味します。つまり、同じ引数を渡した関数はいつも同じ値を返し、状態の変更を引き起こす代入も存在しません。このことを「参照透過性」と呼びます。また、Haskellは「遅延評価」が基本です。つまり、値の計算は必要になったときにはじめて行われます。
Haskellのこれらの性質は、参照透過性のおかげで暗黙の状態がないことから、保守性が高く、また遅延評価のおかげで不必要な計算を避けることができ、無限列を簡単に取り扱うことができます。ただ、純粋関数型言語であるHaskellは、メインストリームの言語とはかなりかけ離れているので、身に着けるのが少々大変というデメリットもあります。
このページで出てきた専門用語
この図では非常に簡略化しています
だから、自分の愛着のある「あの言語」が載っていないからといって、文句を言わないでください。わたし自身、泣く泣く割愛した言語も、多いのです。
数えきれなほどの言語
コンピュータ史上かつて存在した言語の総数は、一説には数千とも数万とも言われています。オモチャのようなプログラミング言語まで含めると、正確な数は誰にも分からないに違いありません。
COBOLもまだまだ現役
人によっては、COBOLに触れる機会はあまりないかもしれません。しかし、例えばわたしの会社(ネットワーク応用通信研究所)では、Linux、PostgreSQLの上にオープンソースCOBOLコンパイラ(OpenCOBOL)とオフコン風トランザクションモニタ(Montsuqi)を開発し、医療系事務システムを開発しています。分野によっては、まだまだ現役なのです。
P言語
Rubyは頭文字が「P」で始まらないので仲間はずれである、と思っていましたが、YAPC::Asia Tokyo 2006で「Rubyはロングテールの付いたP言語である」という発言がありました。これで、晴れてP言語に仲間入りできた……ような、気がします。
世界で一番ユーザーの多い言語
何しろ、Webブラウザを使う人のほぼすべてが、JavaScriptインタープリタ組み込みのブラウザを使っているわけですから。今や、携帯電話にもJavaScriptが載っている時代です。もちろん、JAVAも忘れてはいけません。
Common LispかSchemeのいずれかを意味します
アプリケーション組み込みの分野では、Common LispにもSchemeにも属さないLisp系の言語(例えばEmacs Lispなど)もかなり生き残っています。
Lispの影響を強く受けた
Smalltalk-80は、言語仕様はともかく、内部的にはほとんどLispと同様であったという話もあります。実際、実行モデルのレベルで両言語はかなり似ていますし、実装に使われるテクニックもかなり共通しています。
John Backus
Fortranを設計したプログラマです。
Lispも関数型プログラミング言語
初期のLispでは、あらゆるものに関数という名前がついていたので、しばしば関数型言語と呼ばれました。しかし、同じ引数を与えても異なる値を返すことがあったり、副作用(関数呼び出しがグローバルな状態を変更すること)があったりと、数学的な意味での「関数」型プログラミング言語ではありませんでした。
参考文献
著者について  | |  | ITmedia |
記事の評価
|