| Lisp | |
|---|---|
| パラダイム | マルチパラダイム:機能的、手続き的、反射的、メタ |
| デザイン: | ジョン・マッカーシー |
| 開発者 | スティーブ・ラッセル、ティモシー・P・ハート、マイク・レビン |
| 初登場 | 1960 (1960年) |
| タイピングの規律 | ダイナミック、力強い |
| 方言 | |
| 影響を受けた | |
| 情報処理言語(IPL) | |
| 影響を受けた | |
Lisp(歴史的にはLISP、「リスト処理」の略称)は、長い歴史を持つプログラミング言語ファミリーであり、特徴的な括弧で囲まれたプレフィックス記法を特徴としています。[ 3 ] 1950年代後半に最初に仕様が策定され、 Fortranに次いで現在も広く使用されている 2番目に古い高級プログラミング言語です。[ 4 ] [ 5 ] Lispは初期の頃から変化しており、その歴史の中で多くの方言が存在してきました。今日、最もよく知られている汎用Lisp方言は、Common Lisp、Scheme、Racket、Clojureです。[ 6 ] [ 7 ] [ 8 ]
Lispはもともとコンピュータプログラムのための実用的な数学表記法として開発され、アロンゾ・チャーチのラムダ計算の表記法の影響を受けています(ただし、その表記法から派生したものではありません)。Lispは急速に人工知能(AI)研究で好まれるプログラミング言語となりました。[10 ]最も初期のプログラミング言語の一つとして、Lispは木構造データ構造、自動ストレージ管理、動的型付け、条件文、高階関数、再帰、自己ホスティングコンパイラ、[ 11 ] 、 read-eval-printループなど、コンピュータサイエンスにおける多くのアイデアの先駆者となりました。[ 12 ]
LISPという名前は「リストプロセッサ」に由来しています。[ 13 ]連結リストはLispの主要なデータ構造の一つであり、Lispのソースコードはリストで構成されています。そのため、Lispプログラムはソースコードをデータ構造として操作することができ、プログラマーがLispに埋め込まれた新しい構文や新しいドメイン固有言語を作成できるマクロシステムが生まれました。
コードとデータの互換性により、Lisp はすぐに認識できる構文を実現しています。すべてのプログラムコードはS 式、つまり括弧で囲まれたリストとして記述されます。関数呼び出しや構文形式は、関数名または演算子名を先頭に、引数を後に続けるリストとして記述されます。例えば、f3つの引数を取る関数は と呼ばれます。 (farg1arg2arg3)
歴史
ジョン・マッカーシーは1958年、マサチューセッツ工科大学(MIT)在学中にLispの開発を始めました。彼はIBM 704で動作するAIプログラミング言語を開発したいという思いに突き動かされ、「IBMは人工知能研究を精力的に進めるのに有力な選択肢だ」と考えていました。[ 14 ]彼は同じくリスト処理に基づくInformation Processing Language (IPL)に触発されましたが、異なるハードウェア向けに設計されていたため使用しませんでした。また、代数言語の方が魅力的だと感じました。[ 14 ]これらの要因から、彼はFortranリスト処理言語(List Processing Language)の設計に携わり、Fortranライブラリとして実装されました。しかし、彼はこの言語に満足していませんでした。再帰や現代的なif-then-else文(Lispが初めて導入された当時は新しい概念でした)をサポートしていなかったからです。[注1 ] [ 14 ]
マッカーシーのオリジナルの記法では、括弧で囲まれた「M式」が使用され、これはS式に変換されます。例えば、M式はcar[cons[A,B]]S式と同等です。Lispが実装されると、プログラマーは急速にS式の使用を選択し、M式は放棄されました。[ 14 ] M式は、ホレス・エニアによるMLisp [ 15 ]とヴォーン・プラットによるCGOLの短命な試みによって再び登場しました。 (car(consAB))
Lispは、最初にスティーブ・ラッセルによってIBM 704コンピュータ上でパンチカードを使って実装されました。[ 16 ]ラッセルは当時マッカーシーの下で働いており、Lispのeval関数がマシンコードで実装できることに(マッカーシーを驚かせた)気づきました。
マッカーシーによれば[ 17 ]
スティーブ・ラッセルが「なあ、このevalをプログラムしてみろよ 」と言ったので、私は「おいおい、理論と実践を取り違えているじゃないか。このevalは読むためのものであって、計算するためのものではない」と言った。しかし彼はそれを実行した。つまり、私の論文のevalをIBM 704のマシンコードにコンパイルし、バグを修正した後、これをLispインタープリタとして宣伝したのだ。そして確かにそれはLispだった。つまり、この時点でLispは基本的に今日の形になっていたのだ。
その結果、Lisp プログラムを実行するために、またはより正確には「Lisp 式を評価する」ために使用できる、 実用的な Lispインタープリタが完成しました。
IBM 704用の2つのアセンブリ言語マクロは、リストを分解するための基本操作となりました。car (レジスタ番号のアドレス部分の内容)とcdr(レジスタ番号のデクリメント部分の内容)です。[ 18 ]ここで、「レジスタ」はコンピュータの中央処理装置(CPU)のレジスタを指します。Lisp方言では、リストの最初の項目を返す操作と、リストの残りの項目を返す操作に、それぞれ and (/ k ɑːr /と/ ˈ k ʊ d ər / )が現在も使用されています。carcdr
マッカーシーは1960年4月1日にCommunications of the ACM誌に「記号式の再帰関数と機械による計算、第1部」と題する論文を発表した[ 19 ]。[ 20 ]彼は、いくつかの単純な演算子とチャーチから借用した匿名関数の表記法を使って、アルゴリズムのためのチューリング完全な言語を構築できることを示した。
最初の完全なLispコンパイラはLispで書かれ、1962年にMITのティム・ハートとマイク・レビンによって実装されました。既存のLISPインタープリタにコンパイラコードを解釈させるだけでコンパイルでき、インタープリタの40倍の速度で実行可能な機械語出力を生成することができました。 [ 21 ]このコンパイラは、コンパイルされた関数と解釈された関数を自由に混在させることができる、増分コンパイルというLispモデルを導入しました。ハートとレビンのメモで使用されている言語は、マッカーシーの初期のコードよりも現代のLispスタイルにかなり近いものです。
ガベージコレクションルーチンは、 1962年以前にMITの大学院生ダニエル・エドワーズによって開発されました。 [ 22 ]
1980年代から1990年代にかけて、新しいLisp方言(主にZetaLispやNIL(NewImplementation of Lisp)など、Maclispの後継言語)の作業を単一の言語に統合するための多大な努力が払われました。新しい言語であるCommon Lispは、置き換えた方言とある程度互換性がありました(書籍『Common Lisp the Language』には、様々な構成要素の互換性について記載されています)。1994年、ANSIはCommon Lisp標準規格「ANSI X3.226-1994 情報技術プログラミング言語 Common Lisp」を発行しました。
タイムライン
| 1958 | 1960 | 1965 | 1970 | 1975 | 1980 | 1985 | 1990 | 1995 | 2000 | 2005 | 2010 | 2015 | 2020 | ||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| LISP 1、1.5、LISP 2 (廃止) | |||||||||||||||
| マックリスプ | |||||||||||||||
| インターリスプ | |||||||||||||||
| MDL | |||||||||||||||
| Lispマシン Lisp | |||||||||||||||
| スキーム | R5RS | R6RS | R7RS 小型 | ||||||||||||
| ゼロ | |||||||||||||||
| ZIL (Zork 実装言語) | |||||||||||||||
| フランツ・リスプ | |||||||||||||||
| ミューリスプ | |||||||||||||||
| コモンリスプ | ANSI規格 | ||||||||||||||
| ル・リスプ | |||||||||||||||
| MITスキーム | |||||||||||||||
| XLISP | |||||||||||||||
| T | |||||||||||||||
| シェ・スキーム | |||||||||||||||
| Emacs Lisp | |||||||||||||||
| オートリスプ | |||||||||||||||
| ピコリスプ | |||||||||||||||
| ギャンビット | |||||||||||||||
| ユーリスプ | |||||||||||||||
| ISLISP | |||||||||||||||
| オープンリスプ | |||||||||||||||
| PLTスキーム | ラケット | ||||||||||||||
| ニューリスプ | |||||||||||||||
| GNUガイル | |||||||||||||||
| ビジュアルLISP | |||||||||||||||
| クロージュア | |||||||||||||||
| アーク | |||||||||||||||
| LFE | |||||||||||||||
| ハイ | |||||||||||||||
人工知能とのつながり
Lispは誕生以来、特にPDP-10 [ 23 ]システムにおいて人工知能研究コミュニティと密接な関係にあった。LispはMicro Planner言語の実装として使用され、この言語は有名なAIシステムSHRDLUで使用されていた。1970年代、AI研究から商業的な派生が生まれるにつれ、既存のLispシステムの性能が大きな問題となった。これは、プログラマがLispの実装に関わる様々な技術や選択肢が性能に及ぼす影響について精通する必要があったためである。[ 24 ]
系譜と変種
Lispは60年の歴史の中で、S式言語という中核テーマに基づいて多くのバリエーションを生み出してきました。これらのバリエーションの中には、異なる優先順位を持つ異なるグループによって標準化・実装されたものも存在します(例えば、Common LispとSchemeはどちらも複数の実装を持っています)。しかし、ソフトウェアプロジェクトによっては、標準規格のないLispを定義し、方言と実装の間に明確な区別がない場合もあります(例えば、ClojureとEmacs Lispはこれに該当します)。
方言(および/または実装)間の違いは、非常に顕著な場合があります。例えば、Common Lispでは関数defun名にキーワード を使用しますが、Schemeでは を使用しますdefine。[ 25 ]標準化された方言内では、準拠した実装は同じコア言語をサポートしますが、異なる拡張機能とライブラリを使用します。これにより、ベース言語から非常に目に見える変更が生じることもあります。例えば、Guile(Schemeの実装)は、デフォルト引数やキーワード引数define*を持つ関数を作成するために を使用しますが、どちらも標準化されていません。
歴史的に重要な方言


- LISP 1 [ 26 ] – 最初の実装。
- LISP 1.5 [ 27 ] – MITのマッカーシーらによって開発された、初めて広く配布されたバージョン。オリジナルの「LISP 1」インタプリタにいくつかの改良が加えられていたため、この名前が付けられた。しかし、計画されていたLISP 2のような大幅な再構築は行われなかった。
- スタンフォードLISP 1.6 [ 28 ] –スタンフォードAIラボで開発され、TOPS-10オペレーティングシステムを搭載したPDP-10システムに広く配布されたLISP 1.5の後継。MaclispとInterLispの登場により、時代遅れとなった。
- Maclisp [ 29 ] – MITのProject MAC向けに開発されたMACLISPは、LISP 1.5の直系の後継です。PDP-10およびMulticsシステムで動作しました。MACLISPは後にMaclispと呼ばれるようになり、しばしばMacLispと呼ばれます。MACLISPの「MAC」は、AppleのMacintoshやMcCarthyとは無関係です。
- Interlisp [ 30 ] – BBN Technologies社でTENEXオペレーティングシステムを搭載したPDP-10システム向けに開発され、後にXerox Lispマシン向けの「西海岸」LispとしてInterLisp-Dとして採用されました。「InterLISP 65」と呼ばれる小型版は、MOS Technology 6502ベースのAtari 8ビットコンピュータ向けに公開されました。MaclispとInterLispは強力な競合関係にありました。
- Franz Lisp – 元々はカリフォルニア大学バークレー校のプロジェクトでしたが、後にFranz Inc.によって開発されました。この名前は「Franz Liszt 」の名前をユーモラスに変形したもので、近年Franz Inc.によって販売されているCommon Lispの方言であるAllegro Common Lispを指すものではありません。
- muLISP – 当初はAlbert D. RichとDavid Stoutemeyerによって小型マイクロコンピュータシステム向けに開発されました。1979年に商用化され、64KBのRAMしか搭載していないCP/Mシステムで動作し、後にMS-DOSに移植されました。MS-DOS版の開発は1995年に終了しました。数学ソフトウェア「Derive」は、MS-DOS向けにmuLISPで開発され、その後2007年までWindows向けにも移植されました。
- AutoLISP のベースとなったXLISP。
- Standard LispとPortable Standard Lisp は、特に Computer Algebra System REDUCE で広く使用され、移植されました。
- ZetaLispは Lisp Machine Lisp とも呼ばれ、Lisp マシンで使用され、Maclisp の直系の後継言語です。ZetaLisp は Common Lisp に大きな影響を与えました。
- LeLispはフランス語のLisp方言です。最初のインターフェースビルダーの一つ(SOSインターフェース[ 31 ])はLeLispで書かれました。
- スキーム(1975年)。[ 32 ]
- Common Lisp (1984) は、 Common Lisp the Languageで説明されているように、Maclisp の後継方言[ 33 ]を作成するためのいくつかの異なる試み (ZetaLisp、Spice Lisp、NIL、およびS-1 Lisp )を統合したもので、Scheme 方言からもかなりの影響を受けています。このバージョンの Common Lisp は、幅広いプラットフォームで利用でき、 ANSI Common Lisp (ANSI X3.226-1994) が発行されるまで、事実上の標準[ 34 ]として多くの人に受け入れられていました。Common Lisp の最も普及しているサブ方言には、Steel Bank Common Lisp (SBCL)、CMU Common Lisp (CMU-CL)、Clozure OpenMCL (Clojure と混同しないでください!)、GNU CLisp、およびそれ以降のバージョンの Franz Lisp があり、それらはすべて、後の ANSI CL 標準に準拠しています (以下を参照)。
- Dylan の最初のバージョンは、Scheme と Common Lisp オブジェクト システムを組み合わせたものでした。
- EuLisp – 効率的で整理された新しい Lisp の開発に挑戦します。
- ISLISP – 効率的で整理された新しいLispの開発の試み。ISO/IEC 13816:1997 [ 35 ]として標準化され、後にISO/IEC 13816:2007 [ 36 ]として改訂されました: 情報技術 – プログラミング言語、その環境、およびシステムソフトウェアインターフェース – プログラミング言語ISLISP。
- IEEEスキーム– IEEE 標準、1178–1990 (R1995)。
- ANSI Common Lisp – Common Lispの米国規格協会(ANSI)標準規格。小委員会X3J13によって作成され、[ 37 ] Common Lisp: The Languageを基本文書として策定し、プログラムの移植性とCommon Lisp実装の互換性という共通の課題に対する解決策を見つけるために、公開コンセンサスプロセスを通じて作業を進めることを目的としている。正式にはANSI標準規格であるが、ANSI Common Lispの実装、販売、使用、そして影響力は、これまでも、そしてこれからも、世界中で見られる。
- ACL2または「A Computational Logic for Applicative Common Lisp」は、Common LISP の副作用のない応用型バージョンです。ACL2 は、コンピュータシステムをモデル化できるプログラミング言語であると同時に、それらのモデルの特性を証明するのに役立つツールでもあります。
- Clojure は、 Java 仮想マシンにコンパイルされ、特に並行性を重視したLisp の最近の方言です。
- Game Oriented Assembly Lisp (GOAL)は、ノーティードッグのアンディ・ギャビンによって開発されたビデオゲームプログラミング言語です。Allegro Common Lispを使用して記述され、ノーティードッグが開発したゲーム「Jak and Daxter」シリーズ全体の開発に使用されました。
2000年から現在
Lisp は 1990 年代に多少衰退しましたが、2000 年以降は再び注目を集めています。新しい活動のほとんどは、Common Lisp、Scheme、Emacs Lisp、Clojure、およびRacketの実装に重点が置かれており、新しいポータブル ライブラリとアプリケーションの開発も含まれます。
多くの新しいLispプログラマは、ポール・グラハムやエリック・S・レイモンドといった作家に触発され、他の人々が時代遅れと見なしていた言語を追求するようになりました。新しいLispプログラマはしばしば、この言語を目を見張るような体験と表現し、他の言語よりも大幅に生産性が高いと主張しています。[ 38 ]この認知度の高まりは、「 AIの冬」と1990年代半ばのLispの一時的な人気上昇とは対照的です。 [ 39 ]
2010年時点では、11のCommon Lisp実装が活発にメンテナンスされていました。[ 40 ]
オープンソースコミュニティは、新しい支援インフラを作成しました: CLikiは Common Lisp 関連情報を収集する wiki です。Common Lisp ディレクトリにはリソースがリストされています。#lisp は人気の IRC チャンネルで、コードスニペットの共有やコメントが可能です ( Lisp で書かれた IRC ボットの lisppaste によってサポートされています)。Planet Lisp [ 41 ]はさまざまなLisp関連ブログのコンテンツを集めています。LispForum [ 42 ]ではユーザーが Lisp の話題を議論します。Lispjobs [ 43 ]は求人広告を発表するサービスで、Weekly Lisp Newsという週刊ニュースサービスがあります。Common -lisp.netはオープンソースの Common Lisp プロジェクトのホスティングサイトです。Quicklisp [ 44 ]は Common Lisp のライブラリマネージャです。
Lispの50周年(1958~2008年)はLISP50@OOPSLAで祝われました。[ 45 ]ボストン、バンクーバー、ハンブルクでは定期的にローカルユーザーミーティングが開催されています。その他のイベントには、ヨーロッパCommon Lispミーティング、ヨーロッパLispシンポジウム、国際Lispカンファレンスなどがあります。
Scheme コミュニティは、20 を超える実装を積極的に保守しています。2000 年代には、いくつかの重要な新しい実装 (Chicken、Gambit、Gauche、Ikarus、Larceny、Ypsilon) が開発されました。Scheme のアルゴリズム言語 Scheme に関する改訂第5 版レポート[ 46 ]標準は、Scheme コミュニティで広く受け入れられました。Scheme の実装要求プロセスにより、Scheme の準標準ライブラリと拡張機能が多数作成されました。個々の Scheme 実装のユーザー コミュニティは成長し続けています。新しい言語標準化プロセスは 2003 年に開始され、2007 年に R 6 RS Scheme 標準につながりました。コンピュータ サイエンスの教育における Scheme の学術的使用はやや減少しているようです。一部の大学では、コンピュータ サイエンスの入門コースで Scheme を使用していません。[ 47 ] [ 48 ] MITは現在、学部レベルのコンピュータサイエンスプログラムとMITx大規模公開オンラインコースでSchemeの代わりにPythonを使用しています。[ 49 ] [ 50 ]
Lispには、 Arc、Hy、Nu、Liskell、そしてLFE (Lisp Flavored Erlang)といった新しい方言がいくつかあります。Juliaのパーサーは、 Schemeの方言であるFemtolispで実装されています(JuliaはSchemeに影響を受けており、SchemeもLispの方言です)。
2019 年 10 月、ポール グラハムは「Lisp の新しい方言」 である Bel の仕様をリリースしました。
主要な方言
Common LispとSchemeは、Lisp開発における2つの主要な流れを代表する言語です。これらの言語は、大きく異なる設計上の選択を体現しています。
Common LispはMaclispの後継です。主な影響を受けたのはLisp Machine Lisp、Maclisp、NIL、S-1 Lisp、Spice Lisp、Schemeです。[ 51 ] Lisp Machine Lisp( Lispマシンをプログラムするために使用される大規模なLisp方言)の多くの機能を備えていますが、どのパーソナルコンピュータやワークステーションでも効率的に実装できるように設計されています。Common Lispは汎用プログラミング言語であるため、多くの組み込みデータ型、関数、マクロ、その他の言語要素、およびオブジェクトシステム(Common Lispオブジェクトシステム)を含む大規模な言語標準を持っています。Common Lispは、レキシカルスコープやレキシカルクロージャなどの特定の機能もSchemeから借用しています。 Common Lispの実装は、LLVM、[ 52 ] Java仮想マシン、[ 53 ] x86-64、PowerPC、Alpha、ARM、Motorola 68000、MIPS、[ 54 ] Windows、macOS、Linux、Solaris、FreeBSD、NetBSD、OpenBSD、Dragonfly BSD、Herokuなどのオペレーティングシステムなどのさまざまなプラットフォームを対象に利用できます。[ 55 ]
Scheme は、 Guy L. Steele, Jr.とGerald Jay Sussmanによって発明された Lisp プログラミング言語の静的スコープ付きで適切な末尾再帰の方言です。非常に明快で単純なセマンティクスと、式を形成する数種類の方法を持つように設計されています。Common Lisp より 10 年ほど前に設計されたScheme は、より最小限の設計です。標準機能のセットははるかに少ないですが、Common Lisp では指定されていない特定の実装機能 (末尾呼び出し最適化や完全継続など) があります。命令型、関数型、メッセージ パッシング スタイルを含むさまざまなプログラミング パラダイムで、Scheme での表現が便利です。Scheme は、一連の標準 (アルゴリズム言語 Scheme の改訂レポート) と一連の Scheme 実装要求とともに進化し続けています。
ClojureはLispの方言であり、主にJava仮想マシン、共通言語ランタイム(CLR)、Python VM、Ruby VM YARV、JavaScriptへのコンパイルを対象としています。実用的な汎用言語として設計されています。ClojureはHaskellから多大な影響を受けており、不変性を非常に重視しています。[ 56 ] ClojureはJavaフレームワークやライブラリへのアクセスを提供し、オプションの型ヒントと型推論もサポートしているため、Javaの呼び出しでリフレクションを回避し、高速な基本操作を行うことができます。Clojureは他のLisp方言との下位互換性を持つように設計されていません。[ 57 ]
さらに、Lisp方言は多くのアプリケーションでスクリプト言語として利用されており、最もよく知られているのはEmacsエディタのEmacs Lisp、AutoCADのAutoLISPとその後のVisual Lisp 、 AudacityのNyquist 、LilyPondのSchemeである。Schemeインタープリタはサイズが小さく、組み込みスクリプトとして特に人気がある。例としてSIODとTinySchemeが挙げられ、どちらも「Script-fu」という一般名でGIMP画像処理プロセッサに組み込まれている。 [ 58 ] John Harperによる、元々 Emacs Lisp言語をベースにしたLispインタープリタLIBREPは、 Sawfishウィンドウマネージャに組み込まれている。[ 59 ]
標準化された方言
Lispには公式に標準化された方言があります:R6RS Scheme、R7RS Scheme、IEEE Scheme、[ 60 ] ANSI Common Lisp、ISO ISLISP。
言語革新
ポール・グラハムは、LispがFortranのような既存の言語と異なる9つの重要な側面を挙げている。[ 61 ]
- gotoに限定されない条件文
- ファーストクラス関数
- 再帰
- 変数をポインタとして一律に扱い、型は値に任せる
- ガベージコレクション
- 文を含まず式だけで構成されたプログラム
- シンボルデータ型は文字列データ型とは異なります
- 記号のツリーで構成されたコードの表記法(多くの括弧を使用)
- ロード時、コンパイル時、実行時に完全な言語が利用可能
Lispは、プログラムコードの構造が標準データ構造に忠実かつ直接的に表現された最初の言語でした。この特性は、ずっと後に「同図像性」と呼ばれるようになりました。そのため、Lisp関数は、低レベルの操作を必要とせずに、Lispプログラム内で操作、変更、さらには作成することができます。これは、Lisp言語の表現力に関する主な利点の一つと一般的に考えられており、構文マクロやメタ循環評価に適しています。
if-then-else構文を用いた条件文は、Fortranで書かれたチェスプログラムのためにMcCarthyによって考案されました。彼はこれをALGOLに組み込むことを提案しましたが、 Algol 58仕様には採用されませんでした。Lispでは、McCarthyはより汎用的なcond構造を使用しました。[ 62 ] Algol 60はif-then-elseを採用し、普及させました。
Lisp は、ゼロックス PARCでSmalltalk を開発した研究チームのリーダーであるAlan Kayに大きな影響を与え、次に Lisp は Smalltalk の影響を受け、後の方言は 1970 年代にオブジェクト指向プログラミング機能 (継承クラス、インスタンスのカプセル化、メッセージ パッシングなど) を採用しました。Flavorsオブジェクト システムは、多重継承とmixinの概念を導入しました。Common Lisp オブジェクト システムは、多重継承、多重ディスパッチによるマルチメソッド、およびファーストクラスのジェネリック関数を提供し、柔軟かつ強力な動的ディスパッチを生み出します。これは、その後の多くの Lisp ( Schemeを含む) オブジェクト システムのテンプレートとなっており、多くの場合、メタオブジェクト プロトコル (オブジェクト システムがそれ自身によって定義される反射的なメタ循環設計) を介して実装されています。Lisp は、Smalltalk に次いでこのようなメタオブジェクト システムを備えた 2 番目の言語でした (そして現在でも非常に数少ない言語の 1 つです)。何年も後、アラン・ケイは、これらの特徴の合流の結果として、SmalltalkとLispだけが適切に考えられたオブジェクト指向プログラミングシステムと見なすことができると示唆した。[ 63 ]
Lispは自動ガベージコレクションの概念を導入しました。これは、システムがヒープを巡回して未使用のメモリを探すというものです。世代別ガベージコレクションなどの現代の高度なガベージコレクションアルゴリズムの進歩は、Lispにおけるこの概念の使用によって促進されました。[ 64 ]
エドガー・W・ダイクストラは1972年のチューリング賞講演で次のように述べた。
LISPは、ごく少数の非常に基本的な原理を基盤としながらも、驚くべき安定性を示してきました。それに加え、LISPは、ある意味では最も洗練されたコンピュータアプリケーションの多くを支えてきました。LISPは冗談めかして「コンピュータを誤用する最も賢い方法」と表現されることもあります。私はこの表現は、解放の真の意味を伝えていると言えるため、非常に素晴らしい賛辞だと思います。LISPは、多くの才能ある人類が、これまで不可能だった考えを思いつくのを助けてきました。[ 65 ]
Lispは、初期のコンピューティングハードウェア(初期のマイクロプロセッサを含む)に対するリソース要件が大きかったため、AIコミュニティ以外ではFortranやALGOL由来のC言語ほど普及しませんでした。しかし、複雑で動的なアプリケーションに適していることから、2010年代には再び注目を集めました。[ 66 ]
構文と意味論
- この記事の例はCommon Lispで書かれています (ただし、ほとんどはSchemeでも有効です)。
記号式(S式)
Lispは式指向言語です。他の多くの言語とは異なり、「式」と「文」を区別しません。すべてのコードとデータは式として記述されます。式が評価されると、値(複数の場合もある)が生成され、その値は他の式に埋め込むことができます。それぞれの値は任意のデータ型を取ることができます。
マッカーシーの1958年の論文では、2種類の構文が導入されました。1つはコードとデータの内部表現を反映するシンボリック式(S式、S式)で、もう1つはS式の関数を表現するメタ式(M式)です。M式は結局採用されず、今日のほぼすべてのLispはコードとデータの両方を操作するためにS式を使用しています。
括弧の使い方は、Lisp と他のプログラミング言語ファミリーとの最も明白な違いです。その結果、学生は長い間 Lisp に「馬鹿げた括弧で迷子」や「イライラする余分な括弧がたくさん」などのあだ名を付けてきました。[ 67 ]しかし、S 式の構文も Lisp のパワーの多くを担っています。構文は単純で一貫しており、コンピュータによる操作を容易にしています。ただし、Lisp の構文は従来の括弧表記に限定されません。代替表記を含むように拡張できます。たとえば、XMLisp は、メタオブジェクト プロトコルを使用してS 式を拡張マークアップ言語 ( XML ) と統合する Common Lisp 拡張機能です。
式への依存は、言語に大きな柔軟性をもたらします。Lispの関数はリストとして記述されるため、データと全く同じように処理できます。これにより、他のプログラムを操作するプログラム(メタプログラミング)を容易に記述できます。多くのLisp方言は、マクロシステムを用いてこの機能を活用しており、言語をほぼ無制限に拡張できます。
リスト
Lispのリストは、要素を空白文字, で区切り、括弧で囲んで記述されます。例えば、は、3つのアトム, , を要素とするリストです。これらの値は暗黙的に型付けされます。つまり、それぞれ2つの整数と「シンボル」と呼ばれるLisp特有のデータ型であり、明示的に宣言する必要はありません。 (12foo)12foo
空リスト()は特殊なアトムとして表現されますnil。これはLispにおいて、アトムとリストの両方の要素を持つ唯一の実体です。
式は、接頭辞記法を用いてリストとして記述されます。リストの最初の要素は、関数名、マクロ名、ラムダ式、または「特殊演算子」(下記参照)の名前です。リストの残りの部分は引数です。例えば、関数はlist引数をリストとして返すため、式
(リスト1 2 ( fooを引用))はリスト に評価されます。前の例の の前の「引用符」は「特殊演算子」であり、引数を評価せずに返します。引用符で囲まれていない式は、囲んでいる式が評価される前に再帰的に評価されます。例えば、 (12foo)foo
(リスト1 2 (リスト3 4 ))リスト を評価します。3番目の引数はリストです。リストはネストできます。 (12(34))
オペレーター
算術演算子も同様に扱われます。式
( + 1 2 3 4 )10 と評価されます。中置記法では、同等のものは " " になります。 1+2+3+4
Lispには、 ALGOL派生言語で実装されているような演算子の概念はありません。Lispの算術演算子は可変個引数関数(またはn項関数)であり、任意の数の引数を取ることができます。C言語スタイルのインクリメント演算子「++」は、名前incfを与える構文 で実装されることがあります。
( incf x )と同等で(setq x (+ x 1))、 の新しい値を返しますx。
「特殊演算子」(「特殊形式」と呼ばれることもあります)は、Lispの制御構造を提供します。例えば、特殊演算子はif3つの引数を取ります。最初の引数がnil以外の場合、2番目の引数に評価され、そうでない場合は3番目の引数に評価されます。したがって、式
( nil の場合(リスト1 2 "foo" ) (リスト3 4 "bar" ))は と評価されます。もちろん、 の代わりに非自明な式を代入すれば、これはより便利になります。 (34"bar")nil
Lispには論理演算子and、or、notも用意されています。andとor演算子は短絡評価を行い、それぞれ最初のnilとnil以外の引数を返します。
(または(および"ゼロ" nil "決して" ) "ジェームズ" 'タスク'時間)「James」と評価されます。
ラムダ式と関数定義
もう一つの特殊演算子はlambda、変数を式の中で評価される値に束縛するために用いられます。この演算子は関数の作成にも用いられます。関数の引数はlambda引数のリストと、関数が評価する式(戻り値は最後に評価された式の値)です。式
(ラムダ(引数) ( +引数1 ))は関数として評価され、適用すると1つの引数を取り、それをargその引数より1大きい数値に束縛し、それを返す。ラムダ式は名前付き関数と何ら違いなく扱われ、同じように呼び出される。したがって、式
((ラムダ(引数) ( +引数1 )) 5 )は と評価されます6。ここでは関数適用を行っています。つまり、匿名関数に値 5 を渡して実行します。
名前付き関数は、defun マクロを使用してシンボルにラムダ式を格納することによって作成されます。
( defun foo ( a b c d ) ( + a b c d ))(defunf(a)b...)fグローバル環境で 名前が付けられた新しい関数を定義します。これは概念的に次の式に似ています。
( setf ( fdefinition 'f ) #' ( lambda ( a ) (ブロックf b... )))ここで、 は最初の引数の値を新しい関数オブジェクトにsetf設定するために使用されるマクロです。は、 という名前の関数のグローバル関数定義です。は、関数オブジェクトを返す特殊演算子 の略語です。fdefinition'ffdefinitionf#'function
原子
オリジナルのLISPには、アトムとリストという2つの基本的なデータ型がありました。リストは要素の有限順序付き列で、各要素はアトムまたはリストのいずれかであり、アトムは数値またはシンボルです。シンボルは本質的に一意の名前付き項目であり、ソースコードでは英数字の文字列として記述され、変数名として、またはシンボリック処理ではデータ項目として使用されます。例えば、リストにはシンボル、リスト、および数値2という3つの要素が含まれています。 (FOO(BAR1)2)FOO(BAR1)
アトムとリストの本質的な違いは、アトムは不変かつ一意であるという点です。ソースコード内の異なる場所に出現しながらも、全く同じ方法で記述された2つのアトムは、同じオブジェクトを表します。一方、リストは独立したオブジェクトであり、他のリストとは独立して変更でき、比較演算子によって他のリストと区別できます。
後期のLisp方言でより多くのデータ型が導入され、プログラミングスタイルが進化するにつれて、アトムの概念は重要性を失いました。多くの方言では、レガシー互換性のために述語アトムが保持され、consではない任意のオブジェクトに対して真であると定義されています。
短所とリスト

Lispのリストは、単方向連結リストとして実装されています。[ 68 ]このリストの各セルはcons(Schemeではpair )と呼ばれ、 carとcdrと呼ばれる2つのポインタで構成されています。これらはそれぞれ、連結リストの記事で説明されているフィールドとフィールドに相当します。 datanext
コンスセルから構築できる多くのデータ構造のうち、最も基本的なものの1つは「真リスト」と呼ばれます。真リストは、特殊なnil(空リスト)シンボル、またはcar「データ」(リストなどの別のコンス構造の場合もあります)を指し、「データ」がcdr別の真リストを指すコンスのいずれかです。
与えられたコンスが連結リストの先頭であるとすると、そのcar要素はリストの最初の要素を指し、cdr要素はリストの残りの部分を指します。このため、連結リスト(例えばツリーではなく)の一部であるコンスを参照する場合、 関数carと関数は「および」ともcdr呼ばれます。firstrest
したがって、Lispのリストは、C++やJavaのコンテナクラスのインスタンスのようなアトミックオブジェクトではありません。リストは、連結されたconsの集合に過ぎません。特定のリストを参照する変数は、リストの最初のconsへのポインタです。リストの走査は、リストをcdringで下に移動することで実行できます。つまり、連続したcdrを使ってリストの各consを参照するか、複数の高階関数のいずれかを使用して関数をリストにマッピングすることで実行できます。
LISPシステムではコンスとリストが非常に広く普及しているため、これらがLISPの唯一のデータ構造であるという誤解がよくあります。実際には、最も単純なLISPを除き、ベクター(配列)、ハッシュテーブル、構造体など 、他のデータ構造も存在します。
S式はリストを表す

括弧で囲まれたS式は連結リスト構造を表す。同じリストをS式で表す方法はいくつかある。consはドットペア記法でと書くことができ、 はcarとcdrである。より長い真リストはドットペア記法で書くことができる。これは通常、リスト記法では と省略される。真リストでないリスト[ 69 ]は、最後のcdrが である3つのconsのリスト(すなわち、完全に指定された形式のリスト) のように、2つの組み合わせで書くことができる。(a.b)ab(a.(b.(c.(d.nil))))(abcd)(abc.d)d(a.(b.(c.d)))
リスト処理手順
Lispには、リストにアクセスしたり制御したりするための組み込み手続きが数多く用意されています。list任意の数の引数を取り、それらの引数のリストを返す手続きを使って、リストを直接作成できます。
(リスト1 2 'a 3 ) ;出力: (1 2 a 3)(リスト1 ' ( 2 3 ) 4 ) ;出力: (1 (2 3) 4)リストはコンスペアから構築されるため、このcons手続きはリストの先頭に要素を追加するために使用できます。consリストの構築方法の違いにより、この手続きはリスト引数の処理方法が非対称になります。
( cons 1 ' ( 2 3 )) ;出力: (1 2 3)( cons ' ( 1 2 ) ' ( 3 4 )) ;出力: ((1 2) 3 4)このappend手続きは2つ(またはそれ以上)のリストを互いに追加します。Lispのリストは連結リストであるため、2つのリストを追加するには漸近的な時間計算量が必要です。
( ' ( 1 2 ) ' ( 3 4 )を追加) ;出力: (1 2 3 4)( ' ( 1 2 3 ) ' () ' ( a ) ' ( 5 6 )を追加) ;出力: (1 2 3 a 5 6)共有構造
Lispのリストは単純な連結リストであるため、互いに構造を共有できます。つまり、2つのリストが同じ末尾、つまり最後のcons列を持つことができます。例えば、以下のCommon Lispコードを実行すると、次のようになります。
( setf foo (リスト'a 'b 'c )) ( setf bar ( cons 'x ( cdr foo )))リストfooと はそれぞれとbarです。ただし、リストの末尾は両方のリストで同じ構造です。これはコピーではありません。つまり、とを指すコンスセルは両方のリストで同じメモリ位置にあります。 (abc)(xbc)(bc)bc
構造をコピーするのではなく共有することで、劇的なパフォーマンス向上が期待できます。しかし、この手法は、引数として渡されるリストを変更する関数と望ましくない相互作用を起こす可能性があります。一方のリストを変更する(例えば、cを に置き換える)と、gooseもう一方のリストにも影響が及びます。
( setf ( 3番目のfoo ) 'goose )これはfooに変化しますが、それによって も–に変化します。これは予期せぬ結果となる可能性があります。これはバグの原因となる可能性があり、まさにこの理由から、引数を変更する関数は破壊的であるとドキュメント化されています。 (abgoose)bar(xbgoose)
関数型プログラミングの愛好家は破壊的な関数を避けます。関数型スタイルを重視するScheme方言では、破壊的な関数の名前には注意を促す感嘆符、つまり「bang」が付きます。例えば、set-car!(read set car bang )はconsのcarを置き換えます。Common Lisp方言では破壊的な関数は一般的で、 に相当する関数は「replace car」にちなんでset-car!名付けられていますrplaca。しかし、この関数はほとんど見られません。Common Lispには破壊的な関数の定義と使用を容易にする特別な機能 が含まれているからですsetf。Common Lispでよく使われるスタイルは、プロトタイプ作成時に関数的に(破壊的な呼び出しなしで)コードを記述し、その後、安全に実行できる箇所に最適化として破壊的な呼び出しを追加するというものです。
自己評価フォームと見積り
Lispはユーザーが入力した式を評価します。シンボルとリストは、他の(通常はより単純な)式に評価されます。例えば、シンボルはそれが名付ける変数の値に評価されます。つまり、に評価されます。しかし、他のほとんどの形式はそれ自身に評価されます。Lispに入力された場合、 を返します。 (+23)555
任意の式は、評価されないようにマークすることもできます(シンボルやリストの場合に必要です)。これはquote特殊演算子、またはその省略形'(引用符1つ)の役割です。例えば、通常、シンボル を入力するとfoo、対応する変数の値(または、そのような変数が存在しない場合はエラー)が返されます。リテラルシンボルを参照するには、または と入力します(通常は )。 (quotefoo)'foo
Common LispとSchemeはどちらも、文字(Backtick )で入力されるバッククォート演算子( Schemeではquasiquoteと呼ばれる)をサポートしています。これは通常の引用符とほぼ同じですが、式を評価し、その値をカンマ・アンクォートおよびカンマ・アット・スプライス演算子を使用して引用符で囲まれたリストに挿入することができます。変数が値を持つ場合、は と評価され、 は と評価されます。バッククォートは、マクロ展開の定義で最もよく使用されます。[ 70 ] [ 71 ]`,,@snue(barbaz)`(foo,snue)(foo(barbaz))`(foo,@snue)(foobarbaz)
自己評価型フォームと引用符付きフォームは、Lispにおけるリテラルに相当します。プログラムコード内で(可変の)リテラルの値を変更できる場合があります。例えば、関数が引用符付きフォームを返し、その関数を呼び出すコードがそのフォームを変更すると、それ以降の呼び出しにおける関数の動作が変化する可能性があります。
( defun should-be-constant () ' ( one two three ))( let (( stuff ( should-be-constant ))) ( setf ( third stuff ) 'bizarre )) ; ダメ!(定数であるべき) ; (1 2 奇妙) を返すこのように引用符で囲まれた形式を変更することは、一般的に悪いスタイルであると考えられており、ANSI Common Lisp ではエラーとして定義されています (ファイル コンパイラが類似の定数を結合したり、書き込み保護されたメモリに配置したりする可能性があるため、コンパイルされたファイルで「未定義」の動作が発生します)。
Lisp による引用の形式化は、ダグラス・ホフスタッター(『ゲーデル、エッシャー、バッハ』 ) や他の人々によって、自己言及という哲学的概念の例として指摘されています。
範囲と終了
Lispファミリーは、動的スコープと静的スコープ(レキシカルスコープとも呼ばれる)のどちらを使用するかで意見が分かれています。Clojure、Common Lisp、Schemeはデフォルトで静的スコープを使用しますが、newLISP、Picolisp 、そしてEmacsとAutoCADの組み込み言語は動的スコープを使用します。バージョン24.1以降、Emacsは動的スコープとレキシカルスコープの両方を使用しています。
プログラムコードのリスト構造、マクロとコンパイラによる活用
Lisp と他の言語との根本的な違いは、Lisp ではプログラムのテキスト表現が、基礎となる Lisp システムで使用されるものと同じ内部データ構造 (リンク リスト、シンボル、数値、文字など) を人間が読める形式で単純に記述したものであるという点です。
Lispはこれを利用して、非常に強力なマクロシステムを実装しています。Cプリプロセッサ(C、Objective-C、C++プログラミング言語用のマクロプリプロセッサ)で定義されているマクロ言語など、他のマクロ言語と同様に、マクロはコンパイル可能なコードを返します。しかし、Cプリプロセッサのマクロとは異なり、マクロはLisp関数であるため、Lispの能力を最大限に活用できます。
さらに、Lispコードはリストと同じ構造を持つため、言語内のリスト処理関数のいずれかを使ってマクロを構築できます。つまり、Lispがデータ構造に対して実行できることはすべて、Lispマクロでもコードに対して実行できます。これに対し、他のほとんどの言語では、パーサーの出力は言語実装内部に限定されており、プログラマーが操作することはできません。
この機能により、言語内で効率的な言語を開発することが容易になります。例えば、Common Lispオブジェクトシステムは、マクロを用いた言語拡張として簡潔に実装できます。つまり、アプリケーションで異なる継承メカニズムが必要な場合、異なるオブジェクトシステムを使用できるということです。これは他の多くの言語とは大きく異なります。例えば、Javaは多重継承をサポートしておらず、それを追加する合理的な方法も存在しません。
単純なLisp実装では、このリスト構造はプログラム実行のために直接解釈されます。関数は文字通りリスト構造の一部であり、インタプリタによって実行時に走査されます。しかし、ほとんどの本格的なLispシステムにはコンパイラも含まれています。コンパイラはリスト構造をマシンコードまたはバイトコードに変換して実行します。このコードは、C言語などの従来の言語でコンパイルされたコードと同等の速度で実行できます。
マクロはコンパイル前に展開されるため、いくつかの興味深い選択肢を提供します。プログラムが事前計算されたテーブルを必要とする場合、マクロはコンパイル時にテーブルを作成することができます。その場合、コンパイラはテーブルを出力するだけでよく、実行時にテーブルを作成するためのコードを呼び出す必要はありません。一部のLisp実装には、eval-whenコンパイル時(マクロが必要とする時)にコードが存在し、生成されたモジュールには存在しないことを可能にするメカニズムがあります。[ 72 ]
評価と読み取り-評価-印刷ループ
Lisp言語は、多くの場合、対話型コマンドラインで使用され、統合開発環境(IDE)と組み合わせることもできます。ユーザーはコマンドラインに式を入力するか、IDEに指示してLispシステムに送信します。Lispは入力された式を読み取り、評価し、結果を出力します。このため、Lispコマンドラインはread-eval-print loop(REPL)と呼ばれます。
REPLの基本的な操作は以下の通りです。これは、引用符やマクロなど、実際のLispの多くの要素を省略した簡略化された説明です。
このread関数はテキスト形式のS式を入力として受け取り、それを内部データ構造に変換します。例えば、プロンプトにテキストを入力すると、はこれを3つの要素(シンボル、数値1、数値2)を持つ連結リストに変換します。このリストは有効なLispコードでもあり、評価可能です。これは、リストのcar要素が関数(加算演算)を指定しているためです。 (+12)read+
Afooは単一の記号として読み取られます。123は数字 123 として読み取られます。"123"は文字列 "123" として読み取られます。
関数evalはデータを評価し、結果として0個以上の他のLispデータを返します。評価は必ずしも解釈を意味するわけではありません。一部のLispシステムでは、すべての式をネイティブマシンコードにコンパイルします。しかし、評価を解釈として記述するのは簡単です。carが関数名であるリストを評価するには、evalまずcdrに与えられた各引数を評価し、次に引数に関数を適用します。この場合、関数は加算であり、これを引数リストに適用すると答え が得られます。これが評価の結果です。 (12)3
シンボルはfooシンボルfooの値に評価されます。文字列「123」のようなデータも同じ文字列に評価されます。リストはリスト(1 2 3)に評価されます。 (quote(123))
関数の役割は、printユーザーへの出力を表現することです。3このような単純な結果であれば、これは自明です。リスト構造の一部に評価される式は、printリストを走査してS式として出力する必要があります。
Lisp REPL を実装するには、これら 3 つの関数と無限ループ関数を実装するだけで済みます。(当然、や などevalの特殊演算子もすべて実装する必要があるため、 の実装は複雑になります。) これが完了すると、基本的な REPL は 1 行のコードになります。 iflambda(loop(print(eval(read))))
Lisp REPL は通常、入力編集、入力履歴、エラー処理、デバッガーへのインターフェースも提供します。
Lispは通常、積極的に評価されます。Common Lispでは、引数は適用順序(「最も左から最も内側」)で評価されますが、Schemeでは引数の順序は定義されておらず、コンパイラによる最適化の余地が残されています。
制御構造
Lisp には元々、制御構造がほとんどありませんでしたが、言語の進化の過程で多くの制御構造が追加されました。(Lisp のオリジナルの条件演算子 はcond、後の構造の先駆けですif-then-else。)
Scheme 方言のプログラマーは、ループを末尾再帰を使って表現することが多い。学術的なコンピュータサイエンスにおいて Scheme が広く普及しているため、Lisp で反復処理を記述するには末尾再帰が唯一または最も一般的な方法だと考える学生もいるが、これは間違いである。よく見かける Lisp 方言はすべて、Scheme のdoループからCommon Lispの複雑なloop式まで、命令型の反復構造を持っている。さらに、これを主観的ではなく客観的なものにしている重要な点は、Scheme が末尾呼び出しの処理に関して特定の要件を設けていることであり、したがって、Scheme で末尾再帰の使用が一般に推奨される理由は、この方法が言語定義によって明示的にサポートされているからである。対照的に、ANSI Common Lisp では[ 73 ]一般に末尾呼び出しの削除と呼ばれる最適化は不要である。このように、より伝統的な反復構造(do、またはdolistなどloop)の代わりに末尾再帰スタイルを使用することがCommon Lispでは推奨されていない[ 74 ]という事実は、単に文体の好みの問題ではなく、潜在的に効率性(Common Lispでの明らかな末尾呼び出しは単純なジャンプとしてコンパイルされない可能性があるため)とプログラムの正確性(末尾再帰はCommon Lispでのスタック使用量を増加させ、スタックオーバーフローの危険があるため)の問題でもある。
Lispの制御構造の中には、他の言語の構文キーワードに相当する特殊演算子があります。これらの演算子を用いた式は、関数呼び出しと見た目は同じですが、引数が必ずしも評価されない点、あるいは反復式の場合は複数回評価される点が異なります。
他の主要なプログラミング言語とは異なり、Lispでは言語自体に制御構造を実装できます。多くの制御構造はLispマクロとして実装されており、その動作を知りたいプログラマーはマクロ展開することも可能です。
Common LispとSchemeはどちらも、非局所的な制御フローのための演算子を備えています。これらの演算子の違いは、2つの方言間の最も深い違いの一つです。Schemeは、手続きを用いた再入可能継続call/ccをサポートしており、これによりプログラムは実行中の特定の場所を保存(そして後で復元)することができます。Common Lispは再入可能継続をサポートしていませんが、エスケープ継続を処理するためのいくつかの方法をサポートしています。
Lispでは、同じアルゴリズムを命令型または関数型のどちらのスタイルでも表現できる場合がよくあります。前述のように、Schemeは関数型スタイルを好む傾向があり、制御フローを表現するために末尾再帰と継続を使用します。しかし、命令型スタイルも依然として十分に可能です。多くのCommon Lispプログラマーが好むスタイルは、Cなどの構造化言語に慣れたプログラマーには馴染みがあるかもしれませんが、Schemeプログラマーが好むスタイルは、Haskellなどの純粋関数型言語に近いものです。
Lispはリスト処理という初期の伝統を受け継いでいるため、シーケンスの反復処理に関連する高階関数を幅広く備えています。他の言語(forC言語のループなど)では明示的なループが必要となる場合も、Lispでは高階関数を用いることで同様のタスクを実現できます。(多くの関数型プログラミング言語でも同様です。)
map良い例として、Schemeでは、Common Lispでは と呼ばれる関数が挙げられますmapcar。関数と1つ以上のリストが与えられた場合、mapcar関数をリストの要素に順番に適用し、結果を新しいリストにまとめます。
(マップカー#' + ' ( 1 2 3 4 5 ) ' ( 10 20 30 40 50 ))これにより、+リスト要素の対応する各ペアに関数が適用され、結果が生成されます。 (1122334455)
例
以下は Common Lisp コードの例です。
基本的な「Hello, World!」プログラム:
( "Hello, World!"と印刷)Lispの構文は自然に再帰に適しています。再帰的に定義された集合の列挙といった数学の問題は、この記法で簡単に表現できます。例えば、ある数の階乗を評価するには次のようにします。
( defun階乗( n ) ( if ( zerop n ) 1 ( * n (階乗( 1- n )))))基盤となる Lisp システムが末尾再帰を最適化する場合、代替実装では以前のバージョンよりもスタック スペースが少なくなります。
( defun factorial ( n &optional ( acc 1 )) ( if ( zerop n ) acc ( factorial ( 1- n ) ( * acc n ))))上記の例を、Common Lispのloopマクロを使用する反復バージョンと比較してみましょう。
( defun factorial ( n ) ( iを1からnまでループし、 fac = 1の場合、( * fac i )最後に( facを返す)))次の関数はリストを逆順にします。(Lisp の組み込みのreverse関数も同じことを行います。)
( defun -reverse (リスト) ( let ( (戻り値)) ( dolist ( eリスト) ( push e戻り値))戻り値))オブジェクトシステム
Lispの上に、Lispと並んで、またはLispに組み込んだ様々なオブジェクトシステムやモデルが構築されている。
- Common Lispオブジェクトシステム(CLOS)は、ANSI Common Lispの不可欠な要素です。CLOSはNew FlavorsとCommonLOOPSから派生したものです。ANSI Common Lispは、標準化された最初のオブジェクト指向プログラミング言語でした(1994年、ANSI X3J13)。
- ObjectLisp [ 75 ]またはObject Lisp、Lisp Machines Incorporatedおよび Macintosh Common Lisp の初期バージョンで使用されました。
- LOOPS(Lispオブジェクト指向プログラミングシステム)とその後のCommonLoops
- MITで構築されたFlavorsと、その後継である New Flavors ( Symbolicsによって開発)。
- KR (Knowledge Representation の略) は、Common Lispの GUI ライブラリである Garnet の作成を支援するために開発された制約ベースのオブジェクト システムです。
- 知識工学環境(KEE)はUNITSと呼ばれるオブジェクトシステムを使用し、それを推論エンジン[ 76 ]と真理維持システム(ATMS)と統合しました。
オペレーティングシステム
言語ベースのシステムを含むいくつかのオペレーティングシステムはLispをベースにしている(Lispの機能、規則、メソッド、データ構造などを使用している)、またはLispで書かれている。 [ 77 ]
Genera(Open Generaに改名)[ 78 ] Symbolics社製。Interlispで書かれたMedley(元々はゼロックス社の後期Starワークステーションで実行されていたグラフィカルオペレーティングシステムのファミリー)[ 79 ] [ 80 ] Mezzano、[ 81 ] Interim、[ 82 ] [ 83 ] ChrysaLisp [ 84 ] Tao SystemsのTAOSの開発者によるもの[ 85 ]およびGNU / Linux用の Guixシステム。
参照
脚注
参考文献
- ^ 「Introduction」 . Juliaマニュアル. Read the Docs. 2016年4月8日時点のオリジナルよりアーカイブ。 2016年12月10日閲覧。
- ^ 「Wolfram言語Q&A」 . Wolfram Research . 2016年12月10日閲覧。
- ^エドウィン・D・ライリー (2003).コンピュータサイエンスと情報技術におけるマイルストーン. グリーンウッド出版グループ. pp. 156– 157. ISBN 978-1-57356-521-9。
- ^ "SICP: 序文"。 2001年7月27日時点のオリジナルよりアーカイブ。Lisp
は約25年間使用され続けており、生き残りつつある言語です。現在も使用されているプログラミング言語の中で、Lispよりも長い歴史を持つのはFortranだけです。
- ^ 「結論」 。 2014年4月3日時点のオリジナルよりアーカイブ。2014年6月4日閲覧。
- ^ Steele, Guy L. (1990). Common Lisp: the language (第2版). Bedford, MA: Digital Press. ISBN 1-55558-041-6. OCLC 20631879 .
- ^フェライゼン、マティアス;ロバート・フィンドラー。フラット、マシュー。クリシュナムルティ、シュリラム。バルジライ、エリ。マッカーシー、ジェイ。トービン・ホッホシュタット、サム (2015)。」「ラケット宣言」(PDF)
- ^ 「Clojure - 他のLispとの違い」 . clojure.org . 2022年10月27日閲覧。
- ^ Steele, Guy Lewis; Sussman, Gerald Jay (1978年5月). 「通訳の芸術、あるいはモジュラー性複合体(第0部、第1部、第2部)、第0部、4ページ」 MIT図書館. hdl : 1721.1/6094 . 2020年8月1日閲覧。
- ^ホフスタッター、ダグラス・R. (1999) [1979]、「ゲーデル、エッシャー、バッハ:永遠の黄金の三つ編み(20周年記念版)」、ベーシックブックス、p. 292、ISBN 0-465-02656-7あらゆるコンピュータ言語の中で最も重要かつ魅力的な言語の一つがLISP(リスト処理の略)です。これは、
アルゴルが発明された頃にジョン・マッカーシーによって発明されました。その後、LISPは人工知能分野の研究者の間で大きな人気を博しました。
- ^ポール・グレアム. 「Revenge of the Nerds」 . 2013年3月14日閲覧。
- ^ Chisnall, David (2011-01-12).影響力のあるプログラミング言語 第4部: Lisp .
- ^ジョーンズ、ロビン、メイナード、イアン・スチュワート(2012年12月6日)『Lispプログラミングの芸術』 Springer Science & Business Media、p. 2. ISBN 9781447117193。
- ^ a b c dマッカーシー, ジョン; ウェクスルブラット, リチャード L. (1978).プログラミング言語の歴史. 計算機協会. pp. 173– 183. ISBN 0127450408。
- ^ Smith, David Canfield. MLISP ユーザーズマニュアル(PDF) . 2006年10月13日閲覧。
- ^マッカーシー、ジョン(1979年2月12日)「Lispの歴史:人工知能研究所」(PDF)。
- ^ Stoyan, Herbert (1984-08-06).初期のLISPの歴史 (1956–1959) . LFP '84: Proceedings of the 1984 ACM Symposium on LISP and functional programming. Association for Computing Machinery . p. 307. doi : 10.1145/800055.802047 .
- ^ McCarthy, John. 「LISP の歴史 - 1956年夏から1958年夏まで」 . 2010年3月14日閲覧。
- ^ McCarthy, John (1960). 「記号式の再帰関数と機械による計算、第1部」 Communications of the ACM . 3 (4). Association for Computer Machinery: 184–195 . doi : 10.1145/367177.367199 . 2025年2月28日閲覧。
- ^マッカーシー、ジョン. 「記号式の再帰関数と機械による計算、パートI」 . 2013年10月4日時点のオリジナルよりアーカイブ。 2006年10月13日閲覧。
- ^ハート、ティム、レビン、マイク。「AIメモ39-新しいコンパイラ」(PDF) 。 2017年7月6日時点のオリジナル(PDF)からアーカイブ。 2019年3月18日閲覧。
- ^ McCarthy, John; Abrahams, Paul W.; Edwards, Daniel J.; Hart, Timothy P.; Levin, Michael I. (1985) [1962]. LISP 1.5 プログラマーズ・マニュアル(PDF) . 第15刷 (第2版). p. 序文.
- ^ PDP-6 / PDP-10の36ビットワードサイズは、1ワードに2つのLisp 18ビットポインタを持つことの有用性に影響を受けた。Peter J. Hurley (1990年10月18日). 「TOPSの歴史、あるいは高速ACにおける人生」 .ニュースグループ: alt.folklore.computers . Usenet: [email protected] .
PDP-6プロジェクトは1963年初頭に24ビットマシンとして開始された。設計目標であるLISP向けに36ビットまで拡張された。
- ^ Steele, Guy L.; Gabriel, Richard P. (1996年1月), Bergin, Thomas J.; Gibson, Richard G. (編), "The evolution of Lisp", History of programming languages---II , New York, NY, US: ACM, pp. 233– 330, doi : 10.1145/234286.1057818 , ISBN 978-0-201-89502-5
{{citation}}: CS1 maint: ISBNによる作業パラメータ(リンク) - ^ Common Lisp:
(defun f (x) x)Scheme:(define f (lambda (x) x))または(define (f x) x) - ^ McCarthy, J. ; Brayton, R. ; Edwards, D. ; Fox, P. ; Hodes, L. ; Luckham, D. ; Maling, K. ; Park, D. ; Russell, S. (1960年3月). LISP I Programmers Manual (PDF) . ボストン: MIT Computation Center and Research Laboratory Artificial Intelligence Group .オリジナル(PDF)から2010年7月17日アーカイブ。2010年5月11日にアクセス。
- ^マッカーシー, ジョン; エイブラハムズ, ポール W.; エドワーズ, ダニエル J.; ハート, ティモシー P.; レビン, マイケル I. (1985) [1962]. LISP 1.5 プログラマーズマニュアル(PDF) (第2版). MIT プレス. ISBN 0-262-13011-4。
- ^ Quam, Lynn H.; Diffle, Whitfield. Stanford LISP 1.6 マニュアル(PDF) .
- ^ "Maclisp Reference Manual" . 1979年3月3日. 2007年12月14日時点のオリジナルよりアーカイブ。
- ^ Teitelman, Warren (1974). InterLispリファレンスマニュアル(PDF) . 2006年6月2日時点のオリジナル(PDF)からのアーカイブ。 2006年8月19日閲覧。
- ^インターフェイスの生成と分類: H. El Mrabet による技術と分類
- ^ジェラルド・ジェイ・サスマン&ガイ・ルイス・スティール・ジュニア(1975年12月)「Scheme:拡張ラムダ計算のためのインタープリター」(PDF) MIT AIラボAIM-349 。 2021年12月23日閲覧。
- ^ Steele, Guy L. Jr. (1990). 「目的」 . Common Lisp the Language (第2版). Digital Press. ISBN 0-13-152414-3。
- ^ Kantrowitz, Mark; Margolin, Barry (1996年2月20日). 「歴史:Lispはどこから来たのか?」 . FAQ: Lispに関するよくある質問 2/7 .
- ^ "ISO/IEC 13816:1997" . Iso.org. 2007年10月1日. 2013年11月15日閲覧。
- ^ 「ISO/IEC 13816:2007」 . Iso.org. 2013年10月30日. 2013年11月15日閲覧。
- ^ 「X3J13憲章」。
- ^ 「The Road To Lisp Survey」 。 2006年10月4日時点のオリジナルよりアーカイブ。2006年10月13日閲覧。
- ^ 「未来のトレンド」 Faqs.org。2013年6月3日時点のオリジナルよりアーカイブ。2013年11月15日閲覧。
- ^ Weinreb, Daniel. 「Common Lisp 実装:概観」 . 2012年4月21日時点のオリジナルよりアーカイブ。2012年4月4日閲覧。
- ^ 「Planet Lisp」 . 2023年10月12日閲覧。
- ^ "LispForum" . 2023年10月12日閲覧。
- ^ "Lispjobs" . 2023年10月12日閲覧。
- ^ 「Quicklisp」 . 2023年10月12日閲覧。
- ^ "LISP50@OOPSLA" . Lisp50.org 。2013 年 11 月 15 日に取得。
- ^ Documents: Standards: R5RS . schemers.org (2012-01-11). 2013年7月17日閲覧。
- ^ 「なぜMITは学部レベルのコンピュータサイエンスプログラムにSchemeではなくPythonを採用したのか」 cemerick.com 2009年3月24日。2010年9月17日時点のオリジナルよりアーカイブ。2013年11月10日閲覧。
- ^ Broder, Evan (2008年1月8日). 「時代の終わり」 . mitadmissions.org . 2013年11月10日閲覧。
- ^ 「MIT EECS学部課程」 www.eecs.mit.edu MIT電気工学・コンピュータサイエンス2018年12月31日閲覧。
- ^ 「MITx Python入門コースの登録者数が120万人を突破」 MIT EECS MIT電気工学・コンピュータサイエンス。2021年2月25日時点のオリジナルよりアーカイブ。 2018年12月31日閲覧。
- ^第1.1.2章「履歴」、ANSI CL規格
- ^ [1] ClaspはC++と相互運用し、LLVMを使用してネイティブコードへのジャストインタイムコンパイル(JIT)を行うCommon Lispの実装です
- ^ [2]「Armed Bear Common Lisp (ABCL)は、JVM上で動作するインタプリタとコンパイラを備えたCommon Lisp言語の完全な実装です。」
- ^ [3] 2018年6月22日アーカイブ、Wayback Machine Common Lisp実装:概観
- ^ [4]活発に開発されているCommon Lisp実装の比較
- ^ Clojure コレクションの詳細な考察、2012年6月24日閲覧
- ^ 「Clojure rational」 。 2019年8月27日閲覧。Clojure
は後方互換性に制約されないLispです。
- ^ Script-fu In GIMP 2.4、2009年10月29日閲覧
- ^ librep at Sawfish Wikia、2009年10月29日取得
- ^ 「IEEE Scheme」 . IEEE 1178-1990 - Schemeプログラミング言語のIEEE標準. 2019年8月27日閲覧。
- ^ Paul Graham (2002年5月). 「Lispの違い」
- ^ 「LISPの歴史 - 1956年夏から1958年夏」。
1957年から1958年にかけてMITでIBM 704用にFORTRANで書いたチェスの合法的な動きのルーチンに関連して、私は条件式を発明しました。条件式を定義し、Algolでの使用を提案した論文がACM通信に送られましたが、非常に短かったため、編集者への手紙に格下げされました。
- ^ 「アラン・ケイ博士による『オブジェクト指向プログラミング』の意味」 2003年7月23日。
当時はLISPの巨大なタンジブルメタ言語の考え方は理解できませんでしたが、拡張可能な言語の考え方にはある程度近づいていました。…その第2段階は、最終的にLISPを理解し、その理解に基づいて、より使いやすく、より小さく、より強力で、より遅延束縛された基盤構造を構築することでした。…私にとってOOPとは、メッセージング、状態プロセスのローカルな保持と保護と隠蔽、そしてあらゆるものの極端な遅延束縛を意味します。これはSmalltalkとLISPで実現できます。これが可能な他のシステムもあるかもしれませんが、私は知りません。
- ^リーバーマン、ヘンリー; ヒューイット、カール (1983年6月)、「オブジェクトの寿命に基づくリアルタイムガベージコレクタ」、Communications of the ACM、26 (6): 419– 429、CiteSeerX 10.1.1.4.8633、doi : 10.1145/358141.358147、hdl : 1721.1/6335、S2CID 14161480
- ^エドガー・W・ダイクストラ(1972年)『謙虚なプログラマー』(EWD 340)(ACMチューリング賞講演)
- ^ 「Clojure と Lisp の復活について考える」。
- ^ 「The Jargon File - Lisp」 。 2006年10月13日閲覧。
- ^セベスタ、ロバート W. (2012)。 」「2.4 関数型プログラミング: LISP」;「6.9 リスト型」;「15.4 最初の関数型プログラミング言語: LISP」プログラミング言語の概念(印刷版) (第10版) 。ボストン、マサチューセッツ州、米国:アディソン・ウェスレー。pp. 47– 52, 281– 284, 677– 680。ISBN 978-0-13-139531-2。
- ^注: いわゆる「ドットリスト」は「不適切リスト」の一種に過ぎません。もう一つの種類は、コンスセルがループを形成する「循環リスト」です。これは通常、複数の参照を持つ対象のコンスセルを表すために #n=(...) を使用し、このコンスセルを参照するために #n# を使用します。例えば、(#1=(ab) . #1#) は通常 ((ab) ab) と出力されます (循環構造の出力が有効になっていない場合)。しかし、これによりコンスセルの再利用が明確になります。#1=(a . #1#) は循環構造であるため通常は出力されませんが、(a...) が表示される場合もあります。これは、#1= で定義されるコンスセルの CDR がそれ自身であるためです。
- ^ 「CSE 341: Scheme: Quote, Quasiquote, and Metaprogramming」 . ワシントン大学コンピュータサイエンス&エンジニアリング. 2004年冬. 2013年11月15日閲覧。
- ^ Bawden, Alan. 「LispにおけるQuasiquotation」(PDF) . 2013年6月3日時点のオリジナル(PDF)からのアーカイブ。
- ^「評価時間(Common Lisp拡張)」GNU. 2013年7月17日閲覧。
- ^ 3.2.2.3 Common Lisp HyperSpecにおける意味制約
- ^ 4.3. 制御の抽象化(再帰と反復) Kent PitmanとPeter Norvig著『 Tutorial on Good Lisp Programming Style』、1993年8月。
- ^ Bobrow 1986 17ページ
- ^ Veitch、108ページ、1988年
- ^ Proven, Liam (2022年3月29日). 「C言語以外のオペレーティングシステムのワイルドな世界」 . The Register . 2024年4月4日閲覧。
- ^ 「Symbolics Open Genera 2.0」。GitHubインターネットアーカイブ。2020年1月7日。 2022年2月2日閲覧。
- ^ "Interlisp.org プロジェクト" . Interlisp.org . 2022年3月15日. 2022年2月2日閲覧。
- ^ 「Interlisp Medley」 . GitHub . 2022年3月. 2022年2月2日閲覧。
- ^ froggey (2021年8月1日). “Mezzano” . GitHub . 2022年2月2日閲覧。
- ^ Hartmann, Lukas F. (2015年9月10日). 「Interim」 . Interim-os . 2022年2月2日閲覧。
- ^ Hartmann, Lukas F. (2021年6月11日). 「Interim」 . GitHub . 2022年2月2日閲覧。
- ^ Hinsley, Chris (2022年2月23日). 「ChrysaLisp」 . GitHub . 2022年2月2日閲覧。
- ^スミス、トニー(2013年8月21日)「英国のマイクロテクノロジーのパイオニア、クリス・シェルトン:ナスコム1の背後にある思考」ザ・レジスター。2022年2月2日閲覧。
さらに読む
- マッカーシー、ジョン (1979年2月12日). 「Lispの実装」 . Lispの歴史. スタンフォード大学. 2008年10月17日閲覧.
- Steele, Jr., Guy L.; Richard P. Gabriel (1993). Lispの進化(PDF) . 第2回ACM SIGPLANプログラミング言語史会議. ニューヨーク: ACM. pp. 231– 270. ISBN 0-89791-570-4. 2006年10月12日時点のオリジナル(PDF)からアーカイブ。2008年10月17日閲覧。
- Veitch, Jim (1998). 「CLOSの歴史と解説」. Salus, Peter H. (編). 『プログラミング言語ハンドブック』第4巻, 『関数型プログラミング言語と論理型プログラミング言語』(第1版). インディアナポリス, インディアナ州: Macmillan Technical Publishing. pp. 107–158 . ISBN 1-57870-011-6。
- アベルソン、ハロルド、サスマン、ジェラルド・ジェイ、サスマン、ジュリー(1996). 『コンピュータプログラムの構造と解釈』(第2版). MIT Press. ISBN 0-262-01153-0。
- 私のLisp体験とGNU Emacsの開発、 2002年10月28日、国際Lispカンファレンスでのリチャード・ストールマンのスピーチの記録
- グレアム、ポール(2004年)『ハッカーと画家たち:コンピュータ時代のビッグアイデア』オライリー社、ISBN 0-596-00662-4。
- エドマンド・C・バークレー、ダニエル・G・ボブロウ編(1964年3月)『プログラミング言語LISP:その操作と応用』(PDF)マサチューセッツ州ケンブリッジ:MITプレス
- この記事は主に「LISP - A Simple Introduction」の章に基づいています:Berkeley, Edmund C. (1964年9月). 「プログラミング言語Lisp:入門と評価」 . Computers and Automation : 16-23 .
- ワイスマン、クラーク (1967). LISP 1.5 入門(PDF) . カリフォルニア州ベルモント: ディケンソン出版.
外部リンク
歴史
- Lispの歴史–ジョン・マッカーシーによる1979年2月12日の歴史
- Lisp の歴史– ハーバート・ストヤンの文書からまとめた歴史 (マッカーシー自身も自身のものより完全だと認めている。マッカーシーの歴史のリンクを参照)
- コンピュータ歴史博物館におけるLISPの歴史
- Bell, Adam Gordon (2022年5月2日). LISP in Space, with Ron Garret . CoRecursive (ポッドキャスト、トランスクリプト、写真).NASA ロボットにおける LISP ソフトウェアの使用について。
- Cassel, David (2022年5月22日). 「NASAのプログラマー、深宇宙でのLispデバッグを思い出す」 The New Stack .
協会や会議
書籍とチュートリアル
- LispでSPELをキャストする、漫画スタイルの入門チュートリアル
- Paul Grahamによる無料の本『 On Lisp』
- Practical Common Lisp、フリーウェア版、Peter Seibel 著
- ウェブのためのLisp
- Lispの国
- ラムダを越えて
インタビュー
- ミネソタ大学チャールズ・バベッジ研究所(ミネアポリス)のジョン・マッカーシー氏へのオーラル・ヒストリー・インタビュー。マッカーシー氏は、マサチューセッツ工科大学におけるタイムシェアリング技術の開発における自身の役割について語ります。また、論理ベースAI(LISP)やロボティクスなど、高等研究計画局(APA)の資金提供を受けた人工知能(AI)に関する研究についても説明します。
- リチャード・P・ガブリエル氏へのインタビュー(ポッドキャスト)
リソース