プログラミング言語

プログラミング言語とは、プログラムを記述するための人工言語。コンピュータプログラムを書くために考案された、正確に定義された記号と規則のしくみ。以前は、しばしばプログラム言語と表記された。

1. 概要
-----

プログラミング言語は、情報を組織し処理するタスクについての理解を容易にし、アルゴリズムを正確に表現することができる。特に、チューリング完全であることが特徴である。

言語仕様とプログラムとその入力データの組合せで、そのプログラムを実行したときの結果が完全に指定できなければならない。

プログラミング言語は構文規則と意味規則で定義される。形式的ないし非形式的な仕様が実装とは独立した文書で示される言語もあれば、実装のみの言語もある。

多くの言語は、新たなニーズを満たすべく設計され、他の言語と組み合わされ、最終的に使われなくなる。あらゆる用途に使える万能言語を設計しようという試みはいくつかあったが、そういう意味で成功した言語は存在しない。

プログラミング言語の開発の大きな流れに共通する傾向として、より高いレベルの抽象化によってより高い問題解決能力を得ようとしてきた、ということが指摘されることがある。初期のプログラミング言語はコンピュータのハードウェアのレベルと極めて近かった。新たなプログラミング言語が開発される度に機能が追加され、プログラマはハードウェアの命令からより遠い形でアイデアを表現できるようになっていった。プログラミングをハードウェアから分離することで、プログラマの生産性は向上する。

毎年のように新たなプログラミング言語が作り出されている。2008年2月時点で、「コンピュータ言語辞典」には8,152種のプログラミング言語が記載されていた。

過去のプログラミング言語のなかの欠点と見なされた部分を解消するために、新たなプログラミング言語が構想され、作られてきた歴史がある。また多様なプログラミング言語が生み出される背景には、さまざまな事情があり、ハードウェアが時代とともに変化してきたことや、プログラミング言語というテクノロジーやコンピュータサイエンスの発展も影響しており、下のような諸事情もある。

プログラムと言っても、個人が自分だけのために趣味で書く数行から数十行程度の短いプログラムから、数百人のプログラマが協働して企業の大規模なシステムのために書く長大なプログラムまで、様々なプログラムがある。
プログラミング言語の記述に 簡潔さを求め、可読性が高いことを求め、バグが入り込みにくい記述を好むプログラマの方が多く、世の中では一般的である一方で、ごちゃごちゃして難読で、一名で書くならともかく複数名でプログラムを書くと高頻度で誤読やバグを招きがちな記述でもあまり気にしなかったり面白がる趣味的なプログラマも一部にいる。
プログラムが搭載されるシステムも多様で、マイクロコントローラ、組み込みシステムから汎用デスクトップPC、GPUそしてスーパーコンピュータまで様々あり、それぞれのシステムのハードウェアの特性や制約に合ったプログラムやプログラミング言語がある。
もともとプログラミング言語はもっぱら大学のコンピュータサイエンスの研究室や大手企業の研究所などの奥深くばかりで開発されていたのだが、ここ数十年では個人が趣味的に新しいプログラミング言語を構想しそのコンパイラを自分で書くための書籍なども時折出版されるようになり、つまり世の中の普通の人が新たなプログラミング言語を独自に作成するためのノウハウも広まってハードルが次第に下がってきている。ウィキペディアに記事が掲載されているプログラミング言語を知りたい場合はプログラミング言語一覧を参照のこと。

2. 分類・種類
--------

プログラミング言語の分類法は多数ある。

ひとつの分類法としては、機械寄りか人間寄りか、で分類する方法であり、低水準言語 / 高水準言語 と分類する方法である。 低水準言語の例としては、機械語の「命令コード」と1対1に対応する「命令語」を用いてプログラミングを行うアセンブリ言語がある。対比される高水準言語の例としてはPerl、Visual Basic、LISP、PHP、Java、Pythonなどを挙げることができる。

他の分類法としては、実行方法によってプログラミング言語を分類する方法もあり、インタープリタ方式言語 / コンパイラ方式言語と分類する方法である。 インタープリタ方式言語の例としてはPHPやRubyを挙げることができる。コンパイラ方式言語の例としてはC言語、C++、Erlang、Haskell、Rust、Go、FORTRAN、COBOLなどを挙げることができる。なお言語によってはインタープリタ方式で実行でき、かつコンパイル方式で実行することができるものもある。そして「一応、どちらの方法でも実行できるが、基本はコンパイル方式」などという場合もあるので、やや分類が曖昧になる場合がある。コンパイル方式でしか実行できない言語をわざわざ指さなければならない場合に「純コンパイル方式言語」などと分類する人もいる。なおJavaはバイトコードにコンパイルをしてから実行するので、一応「コンパイル方式」に分類することも可能ではある言語だが、実行時コンパイラとJava仮想マシンを使うので、「Javaは、コンパイル方式とインタープリタ方式の中間的な方式」としばしば指摘され、曖昧な位置づけである。

かつては人間側の用途で分類する方法もしばしば用いられたことがある。たとえば、汎用プログラミング言語 / 事務計算用プログラミング言語/ 科学技術計算用プログラミング言語 などと分類する方法である。1970年代-1980年代などは「事務計算用プログラミング言語の例はCOBOLで、科学技術計算用プログラミング言語の例はFORTRAN」などと書かれたが、近年ではそのような分類はあまりされなくなった。なお「汎用プログラミング言語」に分類されるのはJava、C#、Python、Visual Basic、Rubyなどである。

手続き型言語かそうでないかで、手続き型言語 / 非手続き型言語 と分類する方法もある。手続き型言語の例としてはFORTRAN、ALGOL、C言語、COBOL、BASIC、Pascalなどを挙げることができる。

オブジェクト指向プログラミングに適したしくみを備えているか否かで、オブジェクト指向言語 / 非オブジェクト指向言語 と分類されることもある。

構造化プログラミングに適した仕様になっているか否かで判断して、適したものだけを構造化プログラミング言語と分類する方法もある。

スレッドを複数個生成・管理できるか否か、で並行言語 / 非並行言語 と分類する方法もある。

なお1950年代計算理論をチョムスキー階層という構想や理論が発表された時代には、計算表現能力に基づいてコンピュータの言語を、抽象的に、「タイプ0 / タイプ1 / タイプ2 / タイプ3」などに分類しようとしていたこともあった。ただし近年ではそのような分類法は滅多に持ち出されない。世の中のプログラミング言語のユーザーたちや言語開発者たちの関心は、すでに別のレベルに移っているからである。

プログラミング言語も分類法があまりに多数あるので、混乱しがちな分類法を整理整頓しようと「分類法の分類」をする人も出てくる。たとえば高級言語の分類方法について「プログラミングパラダイムによる分類法 / そうでない分類法」という分類ができる、などと言う人も出てくる。

以上のようにプログラミング言語の分類法は多数あるので、各プログラミング言語は複数のカテゴリに分類可能である。たとえばアセンブリ言語は「低水準言語」に分類され、かつ「非オブジェクト指向言語」に分類される。Javaは「高級言語」に分類され、かつ「オブジェクト指向言語」に分類され、かつ「並行性言語」に分類される。Pythonは「オブジェクト指向言語」であり「スクリプト言語」である。LISPは「マルチパラダイム言語」で「関数型言語」で「手続き型言語」である。

それ以外に、コンピュータがプリンターなどを制御するために使うプログラミング言語を分類するための「ページ記述言語」という分類法もある。 ページ記述言語の代表的な例としては、PostScriptを挙げることができる。たとえば、プリンターで美麗な印字をする場合、画面上のボタンやメニューで「印刷」という命令を選ぶわけだが、その時点でPC内のプリンター制御用プログラムがPostScript言語でプログラムを自動生成し、そのプログラムをケーブルやWifi経由でプリンターに向けて送り出し、それを受け取ったプリンターの側でそれを実行するということで美麗な印字、繊細な曲線に満ちたフォントの印字を実現している。

その他に、あまり真面目な分類ではないが、わざわざ理解が難しくなるように作られたプログラミング言語を特に「難解プログラミング言語」と分類することもある。

3. 歴史
-----

3.1. 初期の発展
----------

「コンピュータ」の定義次第ではあるが、それを「コンピュータ・プログラムによって駆動される機械」とするならば、コンピュータ・プログラムはコンピュータとともに生まれ、育ったということになり、そのプログラムの記法としてプログラミング言語があった、ということになる。チャールズ・バベッジが階差機関に続いて計画した解析機関は、パンチカードの先祖と言えるような穴の開いた厚紙の列によって制御されるという機構を持っていたため、その特徴から「19世紀のコンピュータ」「蒸気動力のコンピュータ」などと呼ばれることがある。

20世紀初頭には、タビュレーティングマシンによってパンチカードを使ったデータの機械処理が始まっている。そういった実際面ばかりではなく計算理論としても、1930年代から1940年代にかけて、アルゴリズムを表現する数学的抽象表現を提供するラムダ計算とチューリングマシンが考案された。ラムダ計算はその後の言語設計にも影響を与えている。

1940年代、世界初の電子式デジタルコンピュータ群が製作された。1950年代初期のコンピュータであるUNIVAC IやIBM 701では機械語を使っていた。機械語によるプログラミングは、間もなくアセンブリ言語によるプログラミングに取って代わられた。1950年代後半になると、アセンブリ言語でマクロ命令が使われるようになり、その後 FORTRAN、LISP、COBOLという3つの高水準言語が開発された。これらは改良を加えられ現在でも使われており、その後の言語開発に重大な影響を与えた。1950年代末、ALGOLが登場し、その後の言語に様々な影響を与えている。初期のプログラミング言語の仕様と使い方は、当時のプログラミング環境の制約にも大きく影響されている。

3.2. 改良
-------

1960年代から1970年代末ごろまでに、現在使われている主な言語パラダイムが開発されたが、その多くはごく初期の第三世代プログラミング言語のアイデアの改良である。

APL - 配列プログラミングを導入した言語。関数型プログラミングにも影響を与えた。
PL/I  - FORTRANとCOBOLの長所を取り入れて1960年代初期に設計された。
Simula - 世界初のオブジェクト指向プログラミングを採用した言語。1970年代中頃には純粋なオブジェクト指向言語であるSmalltalkが登場した。
C言語 - 1969年から1973年にかけてシステムプログラミング言語として開発され、現在でもよく使われている。
Prolog - 1972年に設計された論理プログラミング言語。
ML - 1978年に開発された言語で、LISPをベースとした静的型付け関数型言語の先駆けとなった。これらの言語のアイデアは様々な言語に引き継がれており、現在の言語の多くは、これらのいずれかの系統に属する。

1960年代と1970年代は、構造化プログラミングに関する論争が盛んに行われた時期でもある。この論争で特に有名なものは、1968年にCommunications of the ACMに掲載されたエドガー・ダイクストラのレター//Go To Statement Considered Harmful//であろう。その後の反論と指針としてはクヌースの//Structured Programming with go to Statements//がある。

1960年代と1970年代は、プログラムのメモリ使用量を削減し、プログラマやユーザーの生産性を向上させる技法も進展した時期である。初期の4GLは、同じプログラムを第三世代プログラミング言語で書いたときよりもソースコードの量を劇的に削減した。

3.3. 統合と成長
----------

1980年代は、相対的な統合の時代であった。C++は、オブジェクト指向とシステムプログラミングの統合である。アメリカでは、軍需に使うことを目的としてAdaというシステムプログラミング言語が標準化された。日本などでは、論理プログラミングを応用した第五世代言語の研究に資源を費やした。関数型言語コミュニティではMLとLISPの標準化の動きがあった。これらはいずれも新たなパラダイムを生み出そうというものではなく、それまでに生み出されたアイデアに改良を加える動きであった。

1980年代の重要な言語設計傾向の1つとして、大規模システムのためのプログラミングを目的としてモジュールの概念を採り入れた点が挙げられる。1980年代にモジュールシステムを採り入れた言語として、Modula-2、Ada、MLがあるが、それ以前には、既にPL/Iがモジュラープログラミングをサポートしていた。モジュールシステムはジェネリックプログラミングの構成要素とされることが多い。

1990年代中頃には、インターネットの急激な成長によって新たな言語が生み出される機会が生じた。Perlは1987年にリリースされたUNIX上のスクリプト言語だったが、ウェブサイトの動的コンテンツ作成に使われるようになった。Javaはサーバ側のプログラミングに使われるようになった。

4. 要素
-----

4.1. 構文
-------

プログラミング言語の見た目は、その構文で決定される。図形などを使うグラフィカルなプログラミング言語もあるが、たいていのプログラミング言語のソースコードは文字列である。ファイル形式ではプレーンテキストすなわちテキストファイルが用いられる。

また、たいていのプログラミング言語では、まず、ソースの文字列から空白類を取り除き最小の意味のあるカタマリを取り出した「字句」があり、構文は字句の並びである、という扱いのことが多い。字句を切り出して分類する処理を字句解析、その並びを調べる処理を構文解析という。

字句規則を示すのには正規表現が、そして構文規則を示すのにはバッカス・ナウア記法が使われることが多い。

下記はLISPの構文の一部分である。

expression ::= atom | list
atom ::= number | symbol
number ::= [+-]?[0-9]+
symbol ::= [A-Za-z][^ ]*
list ::= これは、次のような規則である。

expression は atom または list である。
atom は number または symbol である。
number は1文字以上の数字列であり、オプションとして符号が前置される。
symbol はアルファベットで始まる任意の文字列である。
list は括弧記号の対であり、その間に0個以上の expression がある。これに従う例として、12345、、) などがある。

構文上正しいプログラムが全て意味的に整合しているとは限らない、という設計の言語も多い。また、意味的に整合していても、それを書いた人が、自分の意図を正しく反映できていない場合もある。

以下のLISPのコード断片は構文上は正しいが、意味的には問題がある。変数 employees には従業員データのリストを入れるべきものであるが、employees は実際には空なので、employees がリストであることを前提に、employees の後続部分を求める式  は評価できずエラーになる。

) )

4.2. 意味
-------

自然言語の言語学に、そのプログラムが表現しているものは何か、というのが、プログラミング言語の「意味」である。たとえば「a + b という式の値は、aの値とbの値を加算した値である」といったような規則の集まりであり、プログラム意味論という分野で形式的な意味論も研究されているが、C言語の標準規格など、自然言語で意味を与えている言語や、形式的でない擬似言語のようなもので与えている言語もある。

4.3. 型システム
----------

型システムは、プログラミング言語において式の値となるデータ型について、型理論にもとづいて分類しどう扱うかを示すものである。

また、内部的には、ディジタルコンピュータでは全てのデータはバイナリで保持される。

4.3.1. 型のある言語とない言語
------------------

型のある言語は、型システムによって、それぞれの値のデータ型に応じて、定義されていない操作が実行されないようチェックされる機構を持つ。

例えば、"this text between the quotes" は文字列型の値である。ふつう、数を文字列で割る操作には意味がない。そのため、そのようなプログラムは拒絶する。言語によっては、コンパイル時に検出しコンパイルを失敗とする。言語によっては、実行時に検出し、例外とするものもあればなんらかのコアーションを行うものもある。