良くある質問



一般的な質問

Common Lispとはなんですか?

Lispの方言のひとつです。1980年代から1990年代にかけて、乱立するLisp方言を標準化するために生まれました。実用性を強く志向する言語だと言われます。現在ではSchemeと共に、最も有名なLisp方言のひとつです。

Common Lispの情報交換ができる場所はありますか?

有名な所では、comp.lang.lispというニュースグループがあります。英語のニュースグループなので、日本語の文章を投稿しないように気を付けてください。また、Common Lisp Professionalsという、比較的レベルの高い話題を扱うメーリングリストがありますが、こちらも英語話者を対象にするメーリングリストです。

日本語でCommon Lispについて話し合いたい、質問したい場合は、ChatonCOMMON LISP JPというチャットルームが良いでしょう。あるいは、2chを良く利用するなら、プログラム技術板に、比較的活発に情報交換が行われているCommon Lispスレッドがありますので、そちらを利用するのも良いでしょう。

Common Lispの本はありますか?

書籍を見てください。


人名・用語についての質問

John McCarthyとは誰ですか?

Lispを考案した科学者です。初期の人工知能研究の第一人者と言われます。Common Lispの源流の生みの親なので、Common Lisp界隈で良く名前が出ます。

Guy L. Steele, Jr.とは誰ですか?

計算機科学者です。Common Lisp the Languageの著者として、Schemeの共同開発者のひとりとして、C: A Reference Manualの著者として、あるいはジャーゴンファイルの元編集者として、広い分野で有名な人物です。

Paul Grahamとは誰ですか?

Lispの世界での有名人です。Yahoo! Storeを作ったことと、エッセイやCommon Lispについての著作で有名です。詳しくはウィキペディアの記事を見てください。色々と影響力のある人なので、しばしば引き合いに出されます。

CLtLとはなんですか?

Common Lisp the Languageの略です。CLtL2とあった場合、Common Lisp the Language, 2nd Editionの略になります。Guy L. Steele, Jr.がCommon Lispの仕様を記した書籍で、CLtL2はオンライン版もあります。ANSIでCommon Lispが標準化される以前は、これが言語仕様として扱われていました。

CLHSとはなんですか?

Common Lisp HyperSpecのことです。ひとつ下の質問を見てください。

HyperSpecとはなんですか?

Common Lisp HyperSpec(CLHSとも呼ばれます)とは、Common Lispの規格であるANSI INCITS 226-1994 (R2004)(作成された時点ではANSI X3.226-1994 (R1999))をLispWorks社がハイパーテキスト化したものです。言語の規格としては、ANSI INCITS 226-1994 (R2004)が正式なものですが、無料なことと利便性の高さから良く参照されます。

REPLとはなんですか?

Read-Eval-Print Loopの略で、その名の通り、入力の読み込み、評価、結果の表示を繰り返す対話的な環境のことです。一般的に、Common Lispの処理系を起動すると、この環境に入ります。また、SLIMEを起動しても、この環境に入ります。

REPLは、UNIXでいうbashなどのシェルや、Windowsでいうコマンドプロンプトに良く似ています。REPLに入ると、プロンプトが表示されるので(プロンプトの文字は「*」だったり「?」だったり「[数字]>」だったり様々です)、

* 

ここにLispの式を入力すると、

* (+ 2 4)
6
*

のように式を評価した結果が表示され、次の式を受け付けるプロンプトが表示されます。

faslファイルとはなんですか?

Lispの世界では、一般的に、ネイティブ、あるいはバイトコンパイルされたコードが保存されるファイルのことです。compile-fileなどによって作られ、loadによって読まれます。「FASt Loading」の略とされます。

LLGPLとはなんですか?

Lisp Lesser General Public Licenceのことです。ひとつ下の質問を見てください。

Lisp Lesser General Public Licenceとは何ですか?

Lisp Lesser General Public Licenceとは、GNU Lesser General Public License(LGPL)をLispの事情に合わせるため、Franzが考案したライセンスです。LGPLと附則としての前文を組み合わせたもので、ライブラリのリンクについての規定を具体的に示しています。

SLIMEとはなんですか?

SLIME(The Superior Lisp Interaction Mode for Emacs)とは、その名の通り、Emacsで動作するCommon Lisp開発環境です。非常に強力なので、Common Lispユーザから人気があります。

ASDFとはなんですか?

ASDF(Another System Definition Facility)とは、パッケージやソースファイルの依存関係の記述を基に、コンパイルやロードの手順を自動化するためのツールで、C言語におけるmakeやJavaにおけるApache Antに相当します。

ASDF-Installとはなんですか?

ASDF-Installとは、ASDFを利用して、ライブラリのダウンロードからコンパイル、インストールまでを自動でやってくれるツールです。PerlにおけるCPANや、RubyにおけるRubyGemsと似たものと考えていいでしょう。

clbuildとはなんですか?

clbuildASDF-Installと似ていますが、ライブラリの正式なリリースではなく、リポジトリから最新のバージョンをインストールします。

Quicklispとはなんですか?

Quicklispとは、ASDF-Installのように、ライブラリを管理するツールです。OSなどの環境に依存しにくい作りになっているのと、分かりやすい使い勝手が特徴です。

Common-Lisp.netとはなんですか?

Common Lispで書かれたオープンソースのソフトウェアのプロジェクトを対象とした、ホスティングサービスです。

CLikiとはなんですか?

CLikiとは、Common Lispで書かれたWikiクローンであり、そのWikiクローンが動作しているウェブサイトの名前でもあります。海外のユーザが多く集まる場所なので、Common Lispに関する情報を集めるのに便利です。


開発についての質問

統合開発環境はありますか?

Allegro Common LispLispWorksなどの商用処理系には統合開発環境が付いてきます。また、オープンソースのものでは、Emacsで動作するSLIMEが特に有名です。Vimでも、Lispの編集を支援するためのスクリプトが公開されています。

こういった開発環境を利用することで、シンボルを補完したり、インデントを自動的にしたり、コードを簡単にコンパイルできるようになったりします。

日本語を使える処理系はありますか?

データの処理に関しては、多くの処理系で、UnicodeによるUCS Normalizationが採用されています。そのため、Unicodeに収録されている文字なら問題なく扱えるでしょう。

ユーザインターフェイスに関しては、例えば、日本語のメッセージを表示できる処理系はありません。メッセージカタログの仕組み自体はあるCLISPでも、日本語のメッセージカタログがない状況です。

詳しくは処理系:日本語の扱いを見てください。

デバッガを使える処理系はありますか?

ANSI Common Lispで決まっているので、デバッガがない処理系は規格違反です。そのため、ほとんどの処理系にはデバッガがあります。さらに、ブレークポイントとステップ実行も規格によって必要とされるので、こちらもほとんどの処理系が備えています。

ただし、デバッガの機能の細かい部分については決められていないので、それぞれの処理系で機能や操作感に大きな差があります。また、多くはコマンドラインインターフェイスのデバッガで、グラフィカルなデバッガを備えている処理系はあまりありません。

Emacsで動作する統合開発環境のSLIMEを使うことによって、ある程度統一されたインターフェイスでデバッガを操作できるようになります。(スタックトレースのフォーマットなど、細かい部分は処理系ごとに違いが出ます)

インラインアセンブラを使える処理系はありますか?

Steel Bank Common LispEmbeddable Common Lispなど、一部の処理系でインラインアセンブラが使えます。

また、インラインアセンブラではありませんが、FFIを利用することで、ネイティブコードを関数として呼び出す、というトリッキーな代替手段があります。

逆アセンブラはありますか?

ANSI Common Lispで、関数を逆アセンブルするためのdisassembleという関数が決められています。ただし、逆アセンブルした結果のフォーマットは処理系によって違います。

ライブラリはどこで手に入りますか?

Allegro Common Lispなどの商用処理系には強力なライブラリが付属しています。また、Common LispのオープンソースプロジェクトはCommon-Lisp.netに集まっています。CLikiGitHubで探すのも良いでしょう。

ライブラリを配布する方法はプロジェクトによって様々ですが、基本的にはソースコードによる配布です。なので、使う側が自分でライブラリをコンパイルする必要があります。

ソースコードのコンパイルは多くの場合、ASDFによって簡単に行うことができます。プロジェクトによっては、ソースコードのダウンロードからコンパイル、インストールまでを自動でやってくれる、ASDF-InstallclbuildQuicklispといったツールに対応していることもあります。

良いコーディングスタイルはありますか?

Peter NorvigとKent Pitmanが書いた、Tutorial on Good Lisp Programming Styleを読むと良いでしょう。

コーディングスタイルも参考になるかもしれません。

オブジェクト指向プログラミングはできますか?

CLOS(Common Lisp Object System)というオブジェクト指向プログラミングの仕組みがあります。

例外処理はありますか?

コンディションシステムという仕組みがあります。

スレッドには対応していますか?

ANSI Common Lispにはスレッドの仕様は含まれませんが、商用の処理系はもちろん、フリーな処理系でも、独自に対応をしていることがほとんどです。

並行処理には対応していますか?

ANSI Common Lispには並行処理の仕様は含まれませんが、並行処理のためのライブラリはあります。

正規表現は使えますか?

ANSI Common Lispには正規表現の仕様は含まれませんが、CL-PPCREcl-irregsexpなどのライブラリで正規表現を処理できます。

C言語のライブラリを使えますか?

多くの処理系では、FFI(Foreign Function Interface)という仕組みを使って、他言語で作った共有ライブラリを利用できるようになっています。また、処理系のひとつであるEmbeddable Common Lispでは、共有ライブラリや静的ライブラリを直接リンクできます。

実行ファイルは作れますか?

多くの処理系では、実行ファイルも作れるようになっています。詳しくは処理系:実行ファイルの作り方を見てください。ただし、ランタイムライブラリをOSの一部として外部に持つC言語と違い、実行ファイルが巨大になる場合が多いです。

HTTPクライアントはありますか?

Drakmaがあります。

GUIアプリケーションは作れますか?

独自の外観を持つGUIツールキットCLIM(Common Lisp Interface Manager)や、そのオープンソース版であるMcCLIMの他、GTK+QtTkなどを利用するためのライブラリがあります。また、FFIを利用すれば、直接Windows APIを呼び出したりすることもできます。

ユニットテストのフレームワークはありますか?

シンプルなものではlisp-unitCL-TEST-MORE、高機能なものではFiveAMがあります。

マクロをデバッグするにはどうすればいいですか?

マクロを展開するのが手っ取り早いです。macroexpand、macroexpand-1を使うといいでしょう。

(macroexpand-1 '(push :feature-x *features*))
;; =>  (SETQ *FEATURES* (CONS :FEATURE-X *FEATURES*)), T

SLIMEを使っているなら、C-c C-mでmacroexpand-1で、C-c M-mでmacroexpandでマクロを展開した結果を新しいバッファに表示してくれます。

アプリケーションを配布するとき処理系のライセンスに影響を受けますか?

最初に、Allegro CLなどの商用の処理系には、アプリケーションの配布にしっかりとした規定があります。ここで詳しく説明するには長い内容なので、それぞれの処理系のマニュアルなどを読んでください。

フリーの処理系では、採用しているライセンスによって細かな違いが出てきますが、配布が大きく制限されることは基本的にありません。ただし、条件が付く場合がありますので気をつけてください。

まず、処理系のライセンスがパブリックドメイン修正BSDライセンスなら、アプリケーションの配布に問題はありません。実行ファイルで配布して、処理系のカーネルや標準ライブラリなどを含む場合でも、処理系のライセンスはアプリケーションに影響を与えません。ただし、実際は問題にはされないでしょうが、修正BSDライセンスを厳しく解釈するなら、処理系のカーネルや標準ライブラリなどを含む場合、著作権表示やライセンス条文の明示などをしなければいけないかもしれません。

処理系のライセンスがLisp Lesser General Public Licence(LLGPL)なら、アプリケーションの配布に問題はありません。処理系のカーネルや標準ライブラリを含む実行ファイルを作る場合でも、基本的に処理系のライセンスはアプリケーションに影響を与えません。ただし、処理系の機能を拡張する場合は別です。処理系の派生物はLLGPLかGPLにしなければなりません。詳しくはライセンスの本文を確認してください。修正BSDライセンスと同様に、厳しく解釈するなら、カーネルや標準ライブラリを含む場合に著作権表示やライセンス条文の明示が必要です。

処理系のライセンスがGNU General Public License(GPL)でも、アプリケーションの配布には問題はありません。ただし、処理系のライセンスがアプリケーションに影響を与える可能性があります。追加条項がないかどうか、処理系のライセンスを確認してください。CLISPArmed Bear Common LispではGPLに追加条項を加えて、派生物ではないアプリケーションでライセンスの問題が出ないようにしています。こういった追加条項がないなら、GPLの処理系のカーネルや標準ライブラリを含むアプリケーションは、GPLにしなければならないでしょう。

コードの動作にかかる時間を測れますか?

処理系にプロファイラがあればそれを使ってください。あるいは、イベントベースのプロファイラで良ければ、CLiki:Profilerにライブラリがあります。

詳しい計測結果が不要で、単純にかかった時間だけ計測したいときはtimeマクロが便利です。

書いたコードの動作が遅いのですが、どうすれば速くなりますか?

最初に、コードがコンパイルされているかどうか確認してください。コンパイルされていないコードは動作が遅いです。

;; CLISP 2.48での例
(defun fact (n)
  (labels ((rec (n r)
             (if (zerop n)
                 r
                 (rec (1- n) (* n r)))))
    (rec n 1)))

(time (loop repeat 100 do (fact 1000)))
;; コンパイルしていないとき
;-> Real time: 1.015625 sec.
;   Run time: 0.984375 sec.
;   Space: 58878400 Bytes
;   GC: 24, GC time: 0.484375 sec.
;; コンパイルしたとき
;-> Real time: 0.765625 sec.
;   Run time: 0.734375 sec.
;   Space: 58850800 Bytes
;   GC: 25, GC time: 0.5 sec.

次に、最適化宣言をきちんとしているかどうか確認してください。適切に最適化宣言をすることで、処理系が自動的に最適化したオブジェクトコードを作るようになります。標準では、処理系はあまり積極的に最適化をしない設定になっていることが多いので、注意してください。例えば、Clozure CL 1.6では起動直後、全ての設定が1、つまり中立になっています。

この時点でまだ遅いようなら、まず、もっと良いアルゴリズムやデータ構造がないか考えてみてください。同じ計算を何度も繰り返したり、本来は必要のない計算をしていませんか? 要素にランダムアクセスするのにリストを使ったり、要素の挿入や削除が多いのに配列を使ったりしていませんか? 悪い設計は性能を大幅に悪化させます。

;;; データ構造の違いによる性能の差の例

;; リスト
(let ((l (make-list 10000 :initial-element 0)))
  (time (loop repeat 100000 do (nth (random 10000) l))))
;-> (LOOP REPEAT 100000 DO (NTH (RANDOM 10000) L)) took 6,109 milliseconds (6.109 seconds) to run 
;                       with 2 available CPU cores.
;   During that period, 5,719 milliseconds (5.719 seconds) were spent in user mode
;                       171 milliseconds (0.171 seconds) were spent in system mode
;    32 bytes of memory allocated.

;; 配列
(let ((a (make-array 10000 :initial-element 0)))
  (time (loop repeat 100000 do (aref a (random 10000)))))
;-> (LOOP REPEAT 100000 DO (AREF A (RANDOM 10000))) took 15 milliseconds (0.015 seconds) to run 
;                       with 2 available CPU cores.
;   During that period, 16 milliseconds (0.016 seconds) were spent in user mode
;                       0 milliseconds (0.000 seconds) were spent in system mode
;    32 bytes of memory allocated.

より良い設計が思い付かないなら、手動で最適化をします。プロファイラで性能を測り、ボトルネックになっている部分を自分で最適化します。型宣言を付け、コンパイラマクロを使って、特定の条件の式をより高速な式に変換します。

ここまでして、まだ要求する性能に届かないときは、もっと高速なオブジェクトコードを作る処理系に乗り換えるという選択肢があります。または、速度が必要な部分だけCで書き、それをFFIで呼び出す方法もあります。Cで書いてもまだ遅いのであれば、それは設計のミスか、処理自体がその環境で行うには重過ぎるということです。再設計をするか、環境のアップグレードをする必要があるでしょう。


その他の質問

あの変な目がいっぱいある生き物はなんですか?

他言語のプログラマのLispへのイメージだそうです。最近では一部でLispのマスコットとして使われています


Last modified : 2011/12/20 01:18:52 JST
CC0 1.0
Powerd by WiLiKi 0.6.1 on Gauche 0.9