Guajara in other languages: Spanish, Deutsch, English, French, Italian ...



LISP

LISPリスプLISt Processingの略)は 関数型プログラミング言語である。ただし、変数への値の代入(束縛)も可能な、手続き型言語の性格をもっているものもある。

LISPは動的な型付けを行う(値には型情報を持つが変数は型を持たない)、前置記法を持った、コード自身をファーストクラス(一級市民)オブジェクトとして扱うことができる言語である。

機械語アセンブリ言語を除けば、すべての言語を通じてLISPは2番目に古い高級言語であり、現在でも広く使われている。 最古の高級言語Fortranと同様に、LISPの言語仕様は初期のころから大きく変化している。 厳密には、LISPは一つの言語ではなく「LISP方言」と呼ばれる同種の言語の集まりである。

Table of contents
1 LISPの歴史
2 文法
3 最小のLISP
4 プログラム例
5 オブジェクト指向システム
6 系統と変種

LISPの歴史

LISPは1958年MITにいたジョン・マッカーシーによって発明された。マッカーシーは論文再帰関数のS式表現とその計算機上での実行 第一部をCACMで1960年に発表した。 LISPは当初IBM 704上で実装されたが、その計算機上の2つの命令がLISPの基本操作car(Contents of Address Register)、cdr(Contents of Decrement Register)になった。 ほとんどのLISPの方言において、carcdrはそれぞれlistの最初の要素と、最初の要素以外を返す操作である。

その表現力と柔軟性によって、LISPは人工知能のコミュニティで人気を持つようになった。しかし、その実行には大量の内部表現を必要とし、ガーベジコレクションを行う必要があるという弱点にもなっている。 この結果、LISPは貧弱なハードウェア上では実行が困難であった。 1970年代には、増加するユーザコミュニティと寛大な政府の資金提供によって、LISPプログラムの実行に特化したLISPマシンが開発された。 日本でも青山学院大学で開発されたALPS-1などがある。 これは、8080の特定の命令実行を横取りし、ハードウェアでデータを処理させる、という仕組みであった。

1980年代1990年代には、たくさんのLISP方言を一つの言語に統合しようという努力がなされた。 その結果として設計された新しい言語Common LISPは基本的にそれらの方言のスーパーセットであり、それらを置き換えることになった。 1994年ANSIはCommon Lispの標準仕様ANSI X3.226-1994 情報技術プログラミング言語Common LISPを出版した。このときまでには、全盛期に比べるとLISPの市場は小さくなっていた。

LISPは現在でも使われている最古の言語の一つである。AlgolFortranCOBOLも同様の年代物の言語である。FortranやCOBOLはまだ使われている。

文法

LISPは「式指向」の言語である。他の多くの言語とは違って、LISPは式と文の区別をしない。すべてのコードとデータは式として書き下される。 式が評価されたときにはそれは1つの値(もしくは値のリスト)を生成する。式は他の式に埋め込まれることができる。

マッカーシーの1958年の論文は、2つのタイプの文法を導入している。 S式(Symbolic Expression, シンボル式、sexp)と、S式の関数を表すM式(Meta Expression, メタ式)である。 M式には利点がなかったため、今日のほとんどすべてのLISP言語はコードとデータの両方の操作にS式のみを使用する。 S式は括弧を大量に使用するが、そのことで批判も受けてきた。 「LispはLots of Irritating Superfluous Parentheses(過剰でいらいらさせる大量の括弧)の略」というジョークもある。 しかし、S式による構文はLISPの能力を生み出してもいる。 この構文は極めて正規化されているので、コンピュータによる操作が容易なのだ。

式への依存が、LISPに優れた柔軟性を与えている。LISPの関数は、それ自身がリストとして書かれており、データとまったく同様に扱うことができる。 LISPのプログラムは他のLISPプログラムを処理するように書くことができる。 これは、メタプログラミングと呼ばれる。 多くのLISP方言はこの機能をマクロシステムで活用しており、言語自身の機能をほとんど際限なく拡張することを可能にしている。

LISPでのリストは空白と括弧で区切られた要素で記述される。たとえば

(1 2 "foo")

1, 2, "foo"の値を要素としてもつ1つのリストである。これらの値は暗黙の型を持つ。これらは2つの整数と1つの文字列であるが、そのように宣言されている必要はない。 空のリスト()nilも書ける。

式は前置記法のリストとして書かれる。 最初の要素はフォーム(関数か演算子かマクロか特殊フォームのいずれか)の名前である。 リストの残りは引数である。たとえば、関数listはその引数をリストとして返すが、式

(list 1 2 "foo")

は評価されてリスト(1 2 "foo")を返す。 もし引数のどれかが式であれば、それを含む式が評価される前に再帰的に評価される。たとえば、

(list 1 2 (list 3 4))

はリスト(1 2 (3 4))に評価される。 3番目の引数はリストであることに留意する。リストはネストできる。

算術演算も同様に処理される。式

(+ 1 2 3 4)

は10に評価される。この式は中置記法では"1+2+3+4"と等価である。

「特殊フォーム」はLISPの制御構造を提供する。 たとえば、特殊フォームifは3つの引数をとる。 最初の引数がnilでなければ、二番目の引数に評価される。 そうでなければ、第三引数に評価される。したがって式

(if nil
    (list 1 2 "foo")
  (list 3 4 "bar"))

(3 4 "bar")に評価される。(もちろん、この例でのnilのところには自明ではない式がくることで有用になるのである)

その他の特殊形式defunは、関数を定義するために用いられる。 defunの引数は引数のリストと、その関数の結果として評価される式である。

最小のLISP

最小のLISPは、いくつかのC機械語でかかれた関数だけを必要とする。

他のすべての関数は、効率良くではないが、これらの関数に置き換えて定義できるだろう。

プログラム例

以下にいくつかのLISPコード例を示す。 これらは産業界における典型的なコードではないが、コンピュータサイエンスのコースで通常教えられる典型的なLISPコードである。

ここまでの議論で気づいていた読者もいると思うが、LISPの構文はそれ自身が再帰的定義に自然に適合している。 数学的に難解な問題もLISPでは容易に書き下せることが良くある。 皮肉なことに、簡単な仕事を仕上げるのがLISPでは難しくなってしまうこともある。 たとえば、LISPの構文は(手続き型プログラミング言語の様式での)逐次的なタスクの実行(他のプログラミング言語ではここが出発点である)については良く整えられていない。

以下の関数は引数の階乗に評価される。

(defun factorial (n)
  (if (<= n 1)
      1
    (* n (factorial (- n 1)))))

以下は別のやり方であり、末尾再帰になっているのでより効率的であるかもしれない。

(defun factorial (n &optional (acc 1))
  (if (<= n 1)
      acc
    (factorial (- n 1) (* acc n))))

以下の関数はリストを引数にとり、そのリストの要素の順番を逆にしたものに評価される(LISPは実際には同じことを行うビルトイン関数を普通持っている)。

(defun reverse (l &optional acc)
  (if (atom l)
      acc
    (reverse (cdr l) (cons (car l) acc))))

オブジェクト指向システム

以下を含む多種のオブジェクト指向あるいはモジュールがLISPの上に、あるいは併置して、あるいは組み込まれている。

CLOSは多重継承と多重ディスパッチ(「マルチメソッド」)の機能を持ち、「メソッド結合」(FIXME: method combinationの訳語として正しい?)の強力なシステムを持つ。事実上、CLOSを含めたCommon LISPは、公式に標準化された最初のオブジェクト指向言語である。

系統と変種





Wikipedia - All text is available under the terms of the GNU Free Documentation License.

Tagoror dot com  -  Legal Information  -  Contact us