プログラミング言語(プログラミングげんご、)とは、コンピュータに対して命令を行うために設計されている、大抵は形式的に(formalに)定義された構文(シンタックス)と、何らかの意味(セマンティクス)からなる、コンピュータ言語であるLexico, definition of programming language。以前は、しばしばプログラム言語と表記された(#日本語における名称を参照)。プログラミング言語を使って行う作業のことを「プログラミング」といい、プログラミングをする人(あるいはそれを職業にしている人)のことを「プログラマ」という。

プログラミング言語が記述されたもののことを総称して「ソースコード」といい、ソースコードをコンパイルしてできたもののことを「プログラム」という。ソースコードは、原則として文字列や文章の形式を取る(#構文)。

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

言語仕様とプログラムとその入力データの組合せで、そのプログラムを実行したときの結果(外部から観測される振る舞い)が完全に指定できなければならない。

プログラミング言語は構文規則(自然言語に関する言語学で言う統語論の規則に類似したもの)と意味規則(自然言語の意味論に類似した規則)で定義される。形式的ないし非形式的(自然言語による)な仕様が(構文規則は形式的で、意味規則はそうでない、というものが多い)実装とは独立した文書で示される言語もあれば、実装のみの言語もある。

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

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

毎年のように新たなプログラミング言語が作り出されている。2008年2月時点で、「コンピュータ言語辞典The Encyclopedia of Computer Languages (Murdoch University、オーストラリア)」には8,152種のプログラミング言語が記載されていた。

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

ウィキペディアに記事が掲載されているプログラミング言語を知りたい場合はプログラミング言語一覧を参照のこと。

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

低水準言語と高水準言語 ひとつの分類法としては(そして計算機科学や情報処理技術者などの教科書で、まっさきに一種の定番のように挙げてある分類方法としては)、機械寄り(CPU寄り)か人間(の思考)寄りか、で分類する方法であり、低水準言語 / 高水準言語 と分類する方法である。低級言語 / 高級言語 ともいう。

低水準言語の例としては、機械語の「命令コード」CPUの命令コードというのは、本当のCPUレベルではたとえば「00101011」のようにただの2進数の羅列であり、人間には意味不明である。と1対1に対応する「命令語」数文字のアルファベットや数字を組み合わせて、CPUに対する命令やCPUが操作すべきレジスタなどを表記したもの。を用いてプログラミングを行うアセンブリ言語がある(機械語も低水準言語のひとつに数える場合もある。)。

対比される高水準言語の例としてはPerl、Visual Basic、LISP、PHP、Java、Pythonなどを挙げることができる(なお、境界はやや曖昧で、C言語はかつては「高水準言語」と見なされていたが、その後それよりもレベルの高い高水準言語が多数登場したので、今日ではメモリ管理すらしないC言語は「低水準言語」に分類されることもある。)。

インタプリタ方式言語とコンパイラ方式言語 他の分類法としては、標準実装、もしくは一般に利用される実装の実行方法によってプログラミング言語を分類する方法もあり、インタプリタ方式言語() / コンパイラ方式言語(コンパイル方式言語、)と分類する方法である。

この用語はかなり曖昧である。原則として、どの言語もコンパイラやインタプリタで実装できる。実験的な実装まで含めればどちらもある言語が多い。たとえば、典型的なコンパイル方式言語とされるC言語にもインタプリタが存在する。

インタプリタ方式言語の例としてはPHPやRubyを挙げることができる。コンパイラ方式言語の例としてはC言語、C++、Erlang、Haskell、Rust、Go、FORTRAN、COBOLなどを挙げることができる。現状コンパイル方式しか実装が存在しない言語を、わざわざコンパイル方式でしか実行できない言語として指す場合に「純コンパイル方式言語()」などと呼称する人もいるInterpreted vs Compiled Programming Languages: What's the Difference?。

なおJavaはバイトコードにコンパイルをしてから実行するので、一応「コンパイル方式」に分類することも可能ではある。しかしJavaは、実行時コンパイラ (JIT) とJava仮想マシンを使用するので、「インタプリタ方式」に分類することも可能である。しばしば「コンパイル方式とインタプリタ方式の中間的な方式」と指摘され、曖昧な位置づけである。

その他の分類法 この他にも、以下のような分類法が存在する。

アポステリオリ言語 / アプリオリ言語 アプリオリ言語の代表例は、APL、Brainfuck、Emojicode、G、Hoon、J、Light Pattern、、Piet、プランカルキュール、Whitespaceなど。

汎用プログラミング言語 / 事務計算用プログラミング言語 / 科学技術計算用プログラミング言語 汎用プログラミング言語の代表例は、Java、C Sharp、PythonWhat are the best general-purpose programming languages?、Visual Basic、Rubyなど。

手続き型言語 / 非手続き型言語 手続き型言語の代表例は、FORTRAN、ALGOL、C言語、COBOL、BASIC、Pascalなど。

オブジェクト指向言語 / 非オブジェクト指向言語 オブジェクト指向言語の代表例は、Smalltalk、C++、Javaなど。オブジェクト指向プログラミングが行えるかどうかとは関係がなく、そのための機能をメインで提供するかどうかではかられることが多い。

構造化プログラミング言語 / 非構造化プログラミング言語

並行言語 / 非並行言語 スレッドを同時に複数個生成・管理できる言語を並行言語(もしくは並行性言語)、そうでない言語を非並行言語(もしくは非並行性言語)という。

なお、計算理論と関連する、細かく分類するならば形式言語の階層(大雑把にはチョムスキー階層)にもとづき、コンピュータの言語を、抽象的に分類することもできる。しかし、チョムスキーの階層の「タイプ-0」(チューリング完全)がたいていのプログラミング言語であり、他の制限された言語は何らかの特定の問題の難しさの議論であるとか、そういった場合にしか関心を持たれない。

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

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

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

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

歴史

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

20世紀初頭には、タビュレーティングマシンによってパンチカードを使ったデータの機械処理が始まっている。そういった実際面ばかりではなく計算理論としても、1930年代から1940年代にかけて、アルゴリズムを表現する数学的抽象表現を提供するラムダ計算(アロンゾ・チャーチ)とチューリングマシン(アラン・チューリング)が考案された。ラムダ計算はその後の言語設計にも影響を与えているBenjamin C. Pierce は次のように書いている。 ". . . the lambda calculus has seen widespread use in the specification of programming language features, in language design and implementation, and in the study of type systems."(訳:ラムダ計算はプログラミング言語の仕様記述、言語設計と実装、型システムの研究に広く使われている)。

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

改良 1960年代から1970年代末ごろまでに、現在使われている主な言語パラダイムが開発されたが、その多くはごく初期の第三世代プログラミング言語のアイデアの改良である。 APL - 配列プログラミングを導入した言語。関数型プログラミングにも影響を与えたRichard L. Wexelblat: History of Programming Languages, Academic Press, 1981, chapter XIV.。 PL/I (NPL) - FORTRANとCOBOLの長所を取り入れて1960年代初期に設計された。 Simula - 世界初(1960年代)のオブジェクト指向プログラミングを採用した言語。1970年代中頃には純粋なオブジェクト指向言語であるSmalltalkが登場した。 C言語 - 1969年から1973年にかけてシステムプログラミング言語として開発され、現在でもよく使われている. Sorceforge でのプロジェクト群で使われている言語の統計をとった結果である。C言語はよく使われているが、2006年には Java に抜かれている。ただし、C++を含めると一番多く使われていることになる。。 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) は、同じプログラムを第三世代プログラミング言語で書いたときよりもソースコードの量を劇的に削減した。

統合と成長 1980年代は、相対的な統合の時代であった。C++は、オブジェクト指向とシステムプログラミングの統合である。アメリカでは、軍需に使うことを目的としてAdaというシステムプログラミング言語が標準化された。日本などでは、論理プログラミングを応用した第五世代コンピュータの研究に資源を費やした Tetsuro Fujise, Takashi Chikayama, Kazuaki Rokusawa, Akihiko Nakase (December 1994). "KLIC: A Portable Implementation of KL1" Proc. of FGCS '94, ICOT Tokyo, December 1994. 第五世代コンピュータ・プロジェクト・アーカイブ。関数型言語コミュニティではMLとLISPの標準化の動きがあった。これらはいずれも新たなパラダイムを生み出そうというものではなく、それまでに生み出されたアイデアに改良を加える動きであった。

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

1980年代のプログラミング言語の話題としてはもうひとつ、遅延評価の関数型言語のいくつかの提案が挙げられる。似て非なる言語がいくつもあってもしょうがないという動機からHaskellに一本化しようという動きがあらわれ、1990年にHaskell 1.0が作成され、1990年代から2000年代を経て現在までのHaskellの発展に繋がる。

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

要素 構文 thumb|right|292px | 特定の単語だけを別の色へと表示させるシンタックスハイライトという機能によりソースコードの構造や文法ミスを認識しやすくなる。ここでの言語はPython。 | alt= 文字の一部分を別の色へと変えることで、ソースコードの構造誤りや文法誤りを見つけやすくなるようにさせています。この画像では、プログラミング言語のPythonを例にしています。 プログラミング言語の見た目は、その構文(syntax・統語論)で決定される。図形などを使うグラフィカルなプログラミング言語もあるが、たいていのプログラミング言語のソースコードは文字列である。ファイル形式ではプレーンテキストすなわちテキストファイルが用いられる。

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

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

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

expression ::= atom | list atom ::= number | symbol number ::= ['+''-']?['0'-'9']+ symbol ::= ['A'-'Z''a'-'z'][^' ']* list ::= '(' expression* ')'

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

これに従う例として、12345、()、(a b c232 (1)) などがある。

構文上正しいプログラムが全て意味的に整合しているとは限らない、という設計の言語も多い自然言語では Colorless green ideas sleep furiously. という例文がある。その言語の設計次第である。構文的に正しければ必ず整合した意味を持つような設計というものもありうる。。また、意味的に整合していても、それを書いた人が、自分の意図を正しく反映できていない場合もある。

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

(let ((employees nil)) (cdr employees))

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

型システム

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

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

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

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

(型のある言語の特殊例として、単一型言語がある。REXXといったスクリプト言語やSGMLといったマークアップ言語は、単一のデータ型しか扱わない。多くの場合、そのときのデータ型は文字列型である。

アセンブリ言語などの型のない言語は、任意のデータに任意の操作を実行可能であり、データは単にある長さのビット列として扱われる。ある程度高い機能を持ちつつも型が無い(あるいは単一型の)プログラミング言語の例としては、BCPLやForthなどがある(型という概念自体が無いわけではない。例えば「浮動小数点数に対する加算」という演算子といったものは存在する。ただしその演算子により、オペランドが何であれそのワードのビットパターンが浮動小数点数を表現しているものとみなされて加算される、といったようなことになる)。

「多かれ少なかれ」と書いたように、「強い」型システムの言語は少なく、多くの言語はそれなりの型システムを採用している。多くの実用的な言語には、型システムを迂回または打倒するような手段が用意されている。

静的型付けと動的型付け 静的型付け(静的型付き言語)では、全ての式の型はそのプログラムを実行する前(一般にコンパイル時)に決定される。例えば、1とか(2+2)という式は整数型であり、文字列を期待している関数には渡せず、日付(型)を格納するよう定義された変数には代入できない。

静的型付けでは、型を明記する場合と型推論を行う場合がある。前者ではプログラマは適切な位置に型を明記しなければならないたとえば変数の宣言などでは、その名前の直前ないし直後といったことが多い。ただしC言語では「void (*signal(int sig, void (*func)(int)))(int);」などといったように、いったいどこにあるのが名前なのか型なのか、全くわからないことになることがある。。後者では、コンパイラが式の型を文脈から推論する。C++やJavaなどの主な静的型付き言語では、型を明記する。完全な型推論は主流でない言語に使われている(HaskellやML)。ただし、型を明記する言語でも部分的な型推論をサポートしていることが多い。たとえば、JavaやC#では限定された状況で型推論を行う。

動的型付け(動的型付き言語)では、型の安全性は実行時に検査される。言い換えれば、型はソース上の式ではなく、実行時の値に対して付与される。型推論言語と同様、動的型付き言語でも式や変数の型を明記する必要はない。また、ある1つの変数がプログラム実行中に異なる型の値を格納することも可能である。しかし、コードを実際に実行してみるまで型の間違いを自動的に検出することができず、デバッグがやや難しい。動的型付き言語としては、Ruby、LISP、JavaScript、Pythonなどがある。

強い型付けと弱い型付け

実行意味論 データを入力されれば、コンピュータはそのデータに対して何らかの処理を実行する。「実行意味論()」とは、プログラミング言語の構成要素がどの時点でどのようにして、そのプログラムの振る舞いを生成するのかを定義するものである。

例えば、式の評価戦略(先行評価、部分評価、遅延評価、短絡評価など)は実行意味論の一部である。また、制御構造における条件付実行の作法も実行意味論の一部である。

標準ライブラリ 標準ライブラリを参照のこと。

(2025年現在)多くの言語において、各種OS向けの充実した開発環境パッケージを利用することが可能であり、コンパイル時点でチェック/必要なライブラリがあればネットワーク経由で容易に追加できるので、ライブラリの有無を考慮することは少なくなっている。

マクロがライブラリに含まれることもある。C言語では「関数風のマクロ」で提供される機能が存在する。Lisp系の言語では特殊形式の多くが言語組込ではなくマクロで実装可能であり「ifとcond」のように「どちらか片方は必要だが片方があればもう片方はマクロにできる」といったものもある。Schemeの標準規格は、どれを言語組込とし、どれをマクロとするか、ほとんどを処理系実装者の自由に任せている。一方、Common Lispは標準規格でどちらかを決めている。

設計と実装