NikodemusのCommon Lisp FAQ

NikodemusのCommon Lisp FAQ




最終更新:2012-04-13



これは非常に非公式のCommon Lisp FAQで、Nikodemus Siivolaの主観的な意見を反映しています。 このテキストは、インターネットおよびcomp.lang.lispにある他のFAQに一部基づいています。

あなたが私があなたのテキストを使ったと思うなら、私はそれを認めてうれしいので、nikodemus @ random-state.netに書いてください。

このFAQの現在のバージョンは、次のアドレスで入手できます。

http://random-state.net/files/nikodemus-cl-faq.txt

http://random-state.net/files/nikodemus-cl-faq.html

FAQはcomp.lang.lispでも定期的に公開されています。



最初の



Common Lisp CL? クリスプ? Lisp?


「Common Lisp」は、ANSIによって標準化された言語の名前です。

「CL」は、以前の名前の最も好ましい省略形です。

「Clisp」はCommon Lisp実装の1つの名前であるため、適切な略記ではありません。

「Lisp」は、CLが属する言語のカテゴリです。

「LISP」は約20年間書かれなくなりました。CommonLispはLispと略されることがよくあります。

コンテキストから正確に何が議論されているかが明らかです。



それで何?


ここで言語について読むことができます:

http://random-state.net/features-of-common-lisp.html



Common Lispを学ぶには?


  1. Common Lispに関する良い本を読んでください。
  2. それを使い始めてください。


多くの人々は、最初の道を複数回辿ろうとしますが、2番目の道は忘れます。

まあ、真実は、あなたがそれを使い始めなければ言語でプログラムすることを学ぶことができないということです。 そして、かなり大きなプログラムで作業しないと、一般に多くのことを正しく理解することは不可能です。



回避すべき落とし穴は何ですか?


優れた本は、言語の機能とトリックについて説明しますが、多くの人がつまずく心理的および社会的なポイントがいくつかあります。



  1. Lispマクロを学ぶのはおかしい。

    Lispマクロはクールなものですが、初心者に与える力はしばしば混乱を招きます。

    多くの場合、問題の症状は、これが行われる理由を明確に理解せずに何かを実行しようとすることです。 マクロを使用して実行できることはすべて、マクロなしで実行できることを忘れないでください。 もちろん、それはそれほど実用的ではないかもしれませんが、その記憶は天から地に低下します。

    走ることを学ぶ前に、歩くことを学ぶ。 特にそれ以来、飛ぶことができます。
  2. Lispは完璧ではなく、これはニュースではありません。

    Lispに期待を寄せる人もいますが、がっかりしています。 他の人は、LispをX言語と比較し、前者が何かに負けていることを発見します。

    どちらも正しく推論し、合理的な主張をすることができますが、これらの人々がどこか、たとえば#lispで主張を鳴らし始めると問題が始まります。

    推論が正しい場合、問題はすでに100回議論されている可能性が高く、誰もそれを再議論する力や希望を持っていません。

    議論が間違っているか、実際よりも理論的である場合、毎年不満を持っている新参者がそのような質問を絶えず提起するという事実にもかかわらず、誰も再議論する力や欲求を持っていません。

    これは、インターネット上でLispについて悪口を言うことを禁じているという意味ではありませんが、...初心者の場合は、すべてが悪いと言って、人々が両手を広げて来ることを期待しないでください。 たとえあなたが百倍正しいとしても。

    コミュニティのために多くのことを行ってきた高齢者からの苦情には、もっと大きな重みがあります。
  3. 経験豊富な公共の盗聴者は多くのトロルを見ます。

    たくさんのトロリー! 戸惑う初心者は時々トロルのように見えますが、これはほとんどの場合、ほとんどのトロルがLispの初心者を装うからです。

    したがって、人々はあなたがトロルであると考え、それに応じて対応するかもしれません。

    これを避ける最善の方法は礼儀正しくすることです。 誰かがあなたが間違っている、または間違っていると言った場合、彼が正しいか、またはあなたが間違っているか間違っている可能性が高いと考えてください。




どの本から始めますか?


Peter Seibelによる「Practical Common Lisp」(PCLとも呼ばれます)から始めます。 プログラミング言語を既に知っている場合、これは良い出発点です。 この本は、電子形式および印刷形式で入手できます。



http://www.gigamonkeys.com/book/



別の良い本は、Common Lisp:A穏やかなシンボリック計算入門、David Touretzkyです。 プログラミングの初心者またはPCLが複雑すぎると感じる人は、この本を読むべきです。 それから始める場合、それでもPCLを読んでください。 すでにPCLを読んですべてを理解している場合は、これを安全にスキップできます。 この本は、電子形式および印刷形式で入手できます。



http://www.cs.cmu.edu/~dst/LispBook/index.html



良い本はまだたくさんありますが、これら2つは初心者に最適です。 Lispの土地は悪くありませんが、私の謙虚な経験では誤解を形成する可能性があります。 それで始めるなら、とにかくPCLを読んでください。



言語仕様の電子バージョンであるHyperspecまたはCLHSを必ずチェックしてください。 これは単なる貴重なリファレンスです。



http://www.lispworks.com/documentation/HyperSpec/index.html



すぐにガイドを読むために急がないでください。 それがどこにあるかを知っているだけで、CLについて考えられるすべての質問に対する公式の回答が含まれています。 これは、特定のオペレーターが何をしているかを知るのに最適な場所です。 さらに、必要な機能が言語で実装されているかどうかを調べるために調べる価値があります。



また、実装に付属のドキュメントを無視しないでください。 SBCLの場合、マニュアルは次の場所にあります。



http://www.sbcl.org/manual



どの実装を採用すればよいですか?


必要なものに依存しますが、始めたばかりの場合は関係ありません。 ただし、特定のグループからの支援を待っている場合は、このグループが使用する実装を使用してください。



学習するにつれて、情報に基づいた選択ができるようになります。 実装間の移行はそれほど難しくないので、これは痛みを伴う疑いの原因ではありません。



私はSBCLに非常に不満です。



http://www.sbcl.org/



SBCLは、オープンソースが付属し、多くのプラットフォーム(Windowsを含む)で実行され、コンパイラが含まれ、ANSI互換性を非常に真剣に考え、一般に世界に喜びと平和をもたらすため、優れています...私はSBCLの開発者の1人であり、私の会社であるSteel Bank Studio Ltdは彼に商業的なサポートを提供していることに言及してください。



何らかの理由でSBCLがあなたに合わない場合は、次のリストを検討することを提案できます。



開く:





コマーシャル:





ライブラリはどこにありますか? CPANまたはRubyGemsの類似物はありますか?


QuickLispはRubyGemsに非常に似ています:



http://www.quicklisp.org/



大量のライブラリを提供し、それらの間の依存関係を管理します。 これは非常に必要なツールです。



CPANに最も近いのは「Cliki」と「common-lisp.net」です。



http://www.cliki.net/

http://www.common-lisp.net/



...しかし、本当に良いものはありません。



使用するIDE


SBCLを使用する場合は、EmacsとSlimeを使用してください。



http://www.common-lisp.net/project/slime/



Emacsを使用したことがない場合でも、努力してSlimeを使用してください。学習曲線はそれほど急ではなく、すべてのコマンドはメニューからアクセスできます。



Quicklispを使用してSlimeを構成できます。以下の「環境のセットアップ方法」セクションを参照してください。 Mx slime-cheat-sheet



で調査を開始できますが、これはスライム機能のほんの一部です。



別の実装を使用している場合は、開発者が推奨するIDEを使用してください(ただし、Slimeはほとんどすべての実装で動作します)。



Lispでの実用的な作業のために、エディタは少なくとも次のことを行う必要があります。







スライムは、上記のすべてを実行できます。



Vi(m)が好きなら、VimをCommon Lispで書かれたSlimeパートにリンクするSlimvをチェックしてください:



http://www.vim.org/scripts/script.php?script_id=2531

https://bitbucket.org/kovisoft/slimv/

http://kovisoft.bitbucket.org/tutorial.html



...しかし、Vim / Slimvを使用していないため、保証できません。



環境をセットアップする方法は?




SBCLの入手、Slime、Quicklispのセットアップに関する良いガイド(執筆時点)はここにあります:



http://mohiji.nfshost.com/2011/01/modern-common-lisp-on-linux/

http://mohiji.nfshost.com/2011/01/modern-common-lisp-on-osx/



WindowsでClispを構成するためのガイドライン。 ただし、広大なものを受け入れることはできません。



http://mohiji.nfshost.com/2011/01/modern-common-lisp-on-windows/



GUIはありますか?


はい、いいえ。 誰もが使用するGUIはありません。



ほとんどの商用LispにはGUIライブラリが付属しており、これらの実装の支持者は提供されたライブラリを好むようです。 ただし、そのようなライブラリのコードは、Lispの間で移植できません。 商用実装を使用していて、コードの移植性に関心がない場合は、開発者が提供するツールを選択してください。 ライブラリの作成方法に応じて、コードを異なるオペレーティングシステムに移植できます。これはおそらくまさに必要なものです。



オープンソースキャンプにはいくつかの解決策もあります。



CommonQtは、Common LispをQtのスモークライブラリにバインドするものです。



http://common-lisp.net/project/commonqt/



LTKはTkの上に構築されます。



http://www.peter-herth.de/ltk/



CL-GTK2とCLGはGTK +にバインドされていますが、これらの開発の現状については何も言えません。 GTKサーバーを見る価値もあります。



http://common-lisp.net/project/cl-gtk2/

http://sourceforge.net/projects/clg/ http://www.gtk-server.org/



CLIM(Common Lisp Interface Manager)は、GUI用のほぼ標準化されたAPI仕様であり、上記のGUIとはまったく異なります。 すべてが親しみやすく理解できると期待しないでください。



http://random-state.net/files/how-is-clim-different.html



多くの人は、これがGUIを構築するのに最適であると断言しますが、他の人はそれがまったくないことを主張しています。 ほとんどの商用LispにはCLIMが実装されていますが、McCLIMと呼ばれるポータブルなオープンライブラリがまだありますが、最近はあまり開発されていませんが、非常に便利です。



http://common-lisp.net/project/mcclim/



CLXは、X11に匹敵する抽象化レベルを提供する、X11への移植可能な低レベルLispインターフェイスです。



http://www.cliki.net/CLX

https://github.com/sharplispers/clx



GUIの問題に厳密に制限されていない場合、OpenGL、GLU、およびGLUT APIへの移植可能なバインディングであるCL-OPENGLについて言及しなければ、間違っています。



http://common-lisp.net/project/cl-opengl/



どんなフォーラムがありますか?


もちろんフォーラムではありませんが、Common LispのブログアグリゲーターであるPlanet Lispがあります。 たくさんの興味深い情報が、過剰にありません。



http://planet.lisp.org/



LispForumはちょうど良いフォーラムです。



http://www.lispforum.com/



しかし、私は頻繁に行ったことがないので、保証しません。



Usenet / Googleグループにはまだcomp.lang.lispグループがありますが、トロールが密集しています。 そこに書いている著者は非常に読み書きができますが、不敬な憶測は普通の出来事です。 これらのグループを読むのは難しいかもしれませんが、Lispを使用するためにそれらを読む必要はありません。



http://groups.google.com/group/comp.lang.lisp



専門のメーリングリストは、S / N比がはるかに優れています。 すべての実装は、独自のユーザーを作成し、メーリングリストを参照しようとしますが、ほとんどのライブラリも独自のメーリングリストを作成します。 SBCLの場合、たとえば次のとおりです。



https://lists.sourceforge.net/lists/listinfo/sbcl-help



オープンソースの開発者とユーザーの間では、freenode.orgの#lispチャンネルが人気です。 ただし、#lispはこのトピックに非常に厳しい順守を持っていることに注意してください。このトピックは「Lispで」ではなく、Common Lispです。 より柔軟なルールを備えた#lispcafeチャネルがあります。



ゲーム開発者のコ​​ミュニティは非常に活発ですが、私は特にそれに精通していません。 Googleがお手伝いします。



一般的なLispプロフェッショナルは、プロリストでコミュニケーションをとります。 Lispの他の方言の議論は話題外であり、初心者からの質問は受け入れられません。



http://lists.common-lisp.net/mailman/listinfo/pro



言語プロパティ



ファイルをコンパイルする方法は?


簡単な答え: Lispを起動して次を入力:



 (compile-file "/path/to/myfile.lisp")
      
      







次に、ほとんどの場合、コンパイルされたファイルをロード(ロード...)する必要があります。



展開された答え:ほとんどのコンパイル済み言語は非対話型です-コマンドラインまたはIDEからファイルをコンパイルしてから、コンパイル済みファイルを実行します。 Lispでは、これはそうではありません。



一般に、プロジェクトを実行可能ファイルに変換できますが、通常の作業セッションは、予想どおり、編集-コンパイル-実行サイクルとは異なります。



通常、対話は、対話的にコードを追加する作業セッションを含む実行中のLispプロセスと行われます。



例:



  1. Emacsを開き、 Mx slime



    使用してSlimeとLisp Mx slime



    起動します。
  2. たとえば、ASDFを使用して、既存のコードをロードします。
  3. 目的のファイルを開き、関数を編集してCc Cc



    を押すと、再コンパイルが行われます。
  4. Slime REPLに行き、変更をテストします;
  5. 手順3から繰り返します。




上記の略語ASDFは「別のシステム定義機能」の略です。 このシステムでは、単一のコマンドでダウンロードまたはコンパイルするために、複数のファイルを単一のシステムに収集する方法を指定できます。 メイクのようなもの。



実行可能ファイルを作成する方法は?


答えは、使用している実装によって異なります。 ドキュメントを参照してください。 SBCLについて話す場合:



 ;;    SBCL,    save-lisp-and-die. ;;     - MY-FUNCTION. (save-lisp-and-die "my.exe" :executable t :toplevel 'my-function)
      
      







機能と適用-違いは何ですか、何を使用しますか?


簡単な答え: FUNCALL



を使用できる場合はどこでも、他の場合はAPPLY



使用します。



詳細な回答: FUNCALL



呼び出すFUNCALL



引数FUNCALL



数がわかっている必要があります。 APPLY



(およびMULTIPLE-VALUE-CALL



)は、引数の数に関する情報を必要としません。



 (defun map-list-with-1 (function list arg) (mapcar (lambda (elt) (funcall function elt arg)) list)) (defun map-list-with-n (function list &rest args) (mapcar (lambda (elt) (apply function elt args)) list))
      
      







APPLY



を使用してMAP-LIST-WITH-1



を記述する必要はありませんFUNCALL



呼び出すFUNCALL



ほぼ確実に効率的です。



対照的に、 MAP-LIST-WITH-N



は、呼び出し元への引数の数が不明であるため、 FUNCALL



を使用して記述できません。 APPLY



使用する必要があります。



SET、SETQ、SETF-違いは何ですか、何を使用しますか?


簡単な答え:常にSETF



を使用しSETF







詳細な回答:昔々、Common Lispがまだ存在していなかったとき、字句変数はなく、動的変数のみがありました。 そして、 SETQ



SETF



SETF



SET



だけがありました。



今日書かれていること



 (setf (symbol-value '*foo*) 42)
      
      







そのように記録された



 (set (quote *foo*) 42)
      
      







最終的にSETQ



(SET Quoted)に減少しSETQ







 (setq *foo* 42)
      
      







その後、字句変数が出現し、 SETQ



を使用してそれらを割り当てるようになったため、 SETQ



SET



単なるラッパーではなくなりました。



後に、誰かがデータ構造に値を割り当て、他の言語のL値をミラーリングする一般的な方法としてSETF



(SETフィールド)を発明しSETF







 x.car := 42;
      
      







として書かれています



 (setf (car x) 42)
      
      







対称性と一般性のために、 SETF



にはSETQ



機能も含まれてSETQ



ます。 SETQ



は低レベルのプリミティブであり、 SETF



は高レベルの操作であるとSETF



ます。



その後、シンボリックマクロが登場しました。 シンボリックマクロは透過的であるため、割り当てられた「変数」が実際にシンボリックマクロである場合にSETF



SETQ



ように動作するようにSETF



れました。



 (defvar *hidden* (cons 42 42)) (define-symbol-macro foo (car *hidden*)) foo => 42 (setq foo 13) foo => 13 *hidden* => (13 . 42)
      
      







そして今、私たちは最近自分自身を見つけます: SET



SETQ



は本質的にSETQ



あり、古い方言から残されており、おそらく、次のCommon Lispから脱却されるでしょう。



常にSETF



使用しSETF







'(1 2 3)または(list 1 2 3)?


短い答え:書く



 (list 1 2 3)
      
      







違いがわかるまで。 書くなら



 '(1 2 3)
      
      







破壊的に変更しないでください(つまり、 SORT



またはNREVERSE



を使用して)。



展開された答え:最初に、一重引用符は変換するマクロです



 'anything
      
      











 (quote anything)
      
      







読みながら



 '(1 2 3) === (quote (1 2 3))
      
      







第二に、 QUOTE



は引数を計算せずに返す特別な演算子です。 だから



 '(1 2 3)
      
      







リテラルリストを返します。 ほとんどの言語と同様に、リテラルデータを変更すると、未定義の結果が生じます。 たとえば、コンパイラはリテラルを含む定数を連結できます。



 (let ((a '(1 2 3)) (b '(1 2 3))) (eq ab)) ; => T  NIL
      
      







その結果、Aを変更するとBも変更できるという事実がありますが、なぜQUOTE



適しているのでしょうか。 たとえば、コンパイラが結合できる不変の大きなリストがある場合、それらをリテラルとしてマークすると、コンパイラに結合する権利が与えられます。



* EARS *とは何ですか?


変数の宣言に使用するもの、 DEFVAR



またはDEFPARAMETER



、常に* SUCH NAME *を実行します。 また、ローカル変数にはこれを行わないでください。



 (defvar *-* ...) (defvar -- ...)
      
      







なんで? それでも特別な変数が何か分からない場合は、読んでいる本を読み続け、終了したら戻ってください。ただし、今は耳を使ってください。



耳は、非常に簡単な2つの単純な間違いから保護します。



エラー1:特殊変数のランダムバインディング。


 (defparameter foo "foo!") (defun say-it () (write-line foo)) (defun say-more (foo) (say-it) (format t "now say ~A~%" foo))
      
      







いま



 (say-more "bar!")
      
      







印刷します



 say bar! now say bar!
      
      







期待の代わりに



 say foo! now say bar!
      
      







...おっと!



エラー2:タイプミスのため、読み取りはローカル変数ではなく特別なものから行われ、警告は発行されません。


通常、コンパイル時の警告とランタイムエラーが表示されます。



 (defun foo (bar) bat)
      
      







しかし、この前に書く場合



 (defparameter bat "baseball")
      
      







エラーは発生せず、デバッグに多くの時間を費やし、何が間違っているのかを理解しようとします。



自分でコードを作成する場合、耳を置くかどうかはまったく同じですが、コードを公開するとき、*耳*がないことは他の人にとって時間の無駄を意味します。 そうしないでください!



耳の欠如は、エラーの感覚を作成します:私が見るとき



 (defparameter - ...)
      
      







一見すると完全に無害に見えるコードが非ローカルな副作用や依存性を持たないという保証はないため、コードを特に注意深く読む必要があることを理解しています。



常に*耳*を置きます。 彼らはすべてのルールに例外があると言いますが、この場合、このルールの本当の例外を見つけることは非常に困難です。



良いコード

-ニコデマス



All Articles