common-lisp チュートリアル
common-lispの使い方
サーチ…
備考
これはCommon Lispの単純なhello world関数です。例では、 Hello, World!
というテキストが印刷されますHello, World!
(引用符はなく、改行が続きます)を標準出力に追加します。
Common Lispは、REPLとして知られるインタフェースを使用して対話的に使用されるプログラミング言語です。 REPL(Eval Print Loopを読む)では、コードを入力して評価(実行)し、すぐに結果を見ることができます。 REPLのプロンプト(実行するコードをタイプするポイント)は、 CL-USER>
示されます。 CL-USER
以外のものが>
前に現れることがあり>
が、これはまだREPLです。
プロンプトの後に、通常は単一の単語(つまり変数名)またはフォーム( (
と)
間に囲まれた単語/フォームのリスト)(つまり、関数呼び出しや宣言など)があります。次の行には、プログラムが出力する出力(またはプログラムが何も出力しない場合は何も出力されません)と、式を評価することによって返される値があります。通常、式は1つの値を返しますが、複数の値を返す場合は、1行に1回表示されます。
バージョン
バージョン | 発売日 |
---|---|
Common Lisp | 1984-01-01 |
ANSIコモン・リスプ | 1994-01-01 |
こんにちは世界
以下は、Common LispとのREPLセッションからの抜粋であり、 "Hello、World!"関数が定義されて実行されます。 REPLの詳細な説明については、このページの下部にある注釈を参照してください。
CL-USER> (defun hello ()
(format t "Hello, World!~%"))
HELLO
CL-USER> (hello)
Hello, World!
NIL
CL-USER>
これはhello
という名前のゼロ引数の "関数"を定義し、 " "Hello, World!"
という文字列を書き込み"Hello, World!"
標準出力に改行が続き、 NIL
を返します。
書き込む関数を定義するには
(defun name (parameters...)
code...)
この場合、関数はhello
と呼ばれ、パラメータは使用されず、実行されるコードは1つの関数呼び出しを実行することです。 lisp関数から返される値は、実行する関数の最後のビットですhello
は何らかの(format t "Hello, World!~%")
返します。
関数を呼び出すためのlispでは、write (function-name arguments...)
はfunction-name
はfunction-name
で、 arguments...
は呼び出しの引数の(スペースで区切られた)リストです。関数呼び出しのように見える特殊なケースがいくつかありますが、例えば上のコードではdefun
関数が呼び出されず、特殊な扱いを受け、代わりに関数を定義しています。
REPLの2番目のプロンプトでは、 hello
関数を定義した後、それを書いて(hello)
パラメータなしで呼び出します。これは、パラメータt
と"Hello, World!~%"
format
関数を呼び出します。 format
関数は与えられた引数に基づいてフォーマットされた出力を生成しformat
(Cのprintf
高度なバージョンのようなものです)。最初の引数は、どこに出力するかを、 t
は標準出力を意味します。 2番目の引数は何を印刷するか(および余分なパラメータをどのように解釈するか)を指示します。ディレクティブ(2番目の引数の特殊コード) ~%
は、改行を出力するようにformatに指示します(つまり、UNIXの場合は\n
、Windowsの場合は\r\n
)。通常、フォーマットはNIL
(他の言語ではNULL
ようなビット)をNULL
。
2番目のプロンプトの後、 Hello, World
が出力され、次の行に戻り値がNIL
ことがNIL
ます。
こんにちは、名前
これはもう少し高度な例であり、一般的なlispのいくつかの機能を示しています。簡単なHello, World!
から始めましょHello, World!
REPLでインタラクティブな開発を実証しています。セミコロンからの任意のテキスト;
、行の残りの部分はコメントです。
CL-USER> (defun hello ()
(format t "Hello, World!~%")) ;We start as before
HELLO
CL-USER> (hello)
Hello, World!
NIL
CL-USER> (defun hello-name (name) ;A function to say hello to anyone
(format t "Hello, ~a~%" name)) ;~a prints the next argument to format
HELLO-NAME
CL-USER> (hello-name "Jack")
Hello, Jack
NIL
CL-USER> (hello-name "jack") ;doesn't capitalise names
Hello, jack
NIL
CL-USER> (defun hello-name (name) ;format has a feature to convert to title case
(format t "Hello, ~:(~a~)~%" name)) ;anything between ~:( and ~) gets it
WARNING: redefining COMMON-LISP-USER::HELLO-NAME in DEFUN
HELLO-NAME
CL-USER> (hello-name "jack")
Hello, Jack
NIL
CL-USER> (defun hello-name (name)
(format t "Hello, ~:(~a~)!~%" name))
WARNING: redefining COMMON-LISP-USER::HELLO-NAME in DEFUN
HELLO-NAME
CL-USER> (hello-name "jack") ;now this works
Hello, Jack!
NIL
CL-USER> (defun hello (&optional (name "world")) ;we can take an optional argument
(hello-name name)) ;name defaults to "world"
WARNING: redefining COMMON-LISP-USER::HELLO in DEFUN
HELLO
CL-USER> (hello)
Hello, World!
NIL
CL-USER> (hello "jack")
Hello, Jack!
NIL
CL-USER> (hello "john doe") ;note that this capitalises both names
Hello, John Doe!
NIL
CL-USER> (defun hello-person (name &key (number))
(format t "Hello, ~a ~r" name number)) ;~r prints a number in English
HELLO-PERSON
CL-USER> (hello-person "Louis" :number 16) ;this doesn't quite work
Hello, Louis sixteen
NIL
CL-USER> (defun hello-person (name &key (number))
(format t "Hello, ~:(~a ~:r~)!" name number)) ;~:r prints an ordinal
WARNING: redefining COMMON-LISP-USER::HELLO-PERSON in DEFUN
HELLO-PERSON
CL-USER> (hello-person "Louis" :number 16)
Hello, Louis Sixteenth!
NIL
CL-USER> (defun hello-person (name &key (number))
(format t "Hello, ~:(~a ~@r~)!" name number)) ;~@r prints Roman numerals
WARNING: redefining COMMON-LISP-USER::HELLO-PERSON in DEFUN
HELLO-PERSON
CL-USER> (hello-person "Louis" :number 16)
Hello, Louis Xvi!
NIL
CL-USER> (defun hello-person (name &key (number)) ;capitalisation was wrong
(format t "Hello, ~:(~a~) ~:@r!" name number))
WARNING: redefining COMMON-LISP-USER::HELLO-PERSON in DEFUN
HELLO-PERSON
CL-USER> (hello-person "Louis" :number 16) ;thats better
Hello, Louis XVI!
NIL
CL-USER> (hello-person "Louis") ;we get an error because NIL is not a number
Hello, Louis ; Evaluation aborted on #<SB-FORMAT:FORMAT-ERROR {1006641AB3}>.
CL-USER> (defun say-person (name &key (number 1 number-p)
(title nil) (roman-number t))
(let ((number (if number-p
(typecase number
(integer
(format nil (if roman-number " ~:@r" " ~:(~:r~)") number))
(otherwise
(format nil " ~:(~a~)" number)))
"")) ; here we define a variable called number
(title (if title
(format nil "~:(~a~) " title)
""))) ; and here one called title
(format nil "~a~:(~a~)~a" title name number))) ;we use them here
SAY-PERSON
CL-USER> (say-person "John") ;some examples
"John"
CL-USER> (say-person "john doe")
"John Doe"
CL-USER> (say-person "john doe" :number "JR")
"John Doe Jr"
CL-USER> (say-person "john doe" :number "Junior")
"John Doe Junior"
CL-USER> (say-person "john doe" :number 1)
"John Doe I"
CL-USER> (say-person "john doe" :number 1 :roman-number nil) ;this is wrong
"John Doe First"
CL-USER> (defun say-person (name &key (number 1 number-p)
(title nil) (roman-number t))
(let ((number (if number-p
(typecase number
(integer
(format nil (if roman-number " ~:@r" " the ~:(~:r~)") number))
(otherwise
(format nil " ~:(~a~)" number)))
""))
(title (if title
(format nil "~:(~a~) " title)
"")))
(format nil "~a~:(~a~)~a" title name number)))
WARNING: redefining COMMON-LISP-USER::SAY-PERSON in DEFUN
SAY-PERSON
CL-USER> (say-person "john doe" :number 1 :roman-number nil) ;thats better
"John Doe the First"
CL-USER> (say-person "louis" :title "king" :number 16 :roman-number nil)
"King Louis the Sixteenth"
CL-USER> (say-person "louis" :title "king" :number 16 :roman-number t)
"King Louis XVI"
CL-USER> (defun hello (&optional (name "World") &rest arguments) ;now we will just
(apply #'hello-name name arguments)) ;pass all arguments to hello-name
WARNING: redefining COMMON-LISP-USER::HELLO in DEFUN
HELLO
CL-USER> (defun hello-name (name &rest arguments) ;which will now just use
(format t "Hello, ~a!" (apply #'say-person name arguments))) ;say-person
WARNING: redefining COMMON-LISP-USER::HELLO-NAME in DEFUN
HELLO-NAME
CL-USER> (hello "louis" :title "king" :number 16) ;this works now
Hello, King Louis XVI!
NIL
CL-USER>
これは、Common Lispのformat
関数の高度な機能の一部と、オプションのパラメータやキーワード引数(例:number
)などのいくつかの機能を強調しています。これはまた、共通のリスプでREPLでインタラクティブな開発の例を示しています。
REPLの簡単なHello Worldプログラム
Common Lisp REPLはインタラクティブな環境です。プロンプト後に書かれたすべてのフォームが評価され、その値は評価の結果として後で印刷されます。ですから、Common Lispの最も簡単な "Hello、World!"プログラムは次のとおりです:
CL-USER> "Hello, World!"
"Hello, World!"
CL-USER>
ここで起こるのは、REPLへの入力で文字列コストが与えられ、評価され、結果が出力されることです。この例から分かるように、数字のような文字列、 NIL
やT
などの特殊記号やその他のリテラルは、 自己評価型です。つまり、それは自分自身に評価されます。
基本式
REPLで基本的な表現を試してみましょう:
CL-USER> (+ 1 2 3)
6
CL-USER> (- 3 1 1)
1
CL-USER> (- 3)
-3
CL-USER> (+ 5.3 (- 3 2) (* 2 2))
10.3
CL-USER> (concatenate 'string "Hello, " "World!")
"Hello, World!"
CL-USER>
Common Lispプログラムの基本的なビルディングブロックはフォームです。私たちは関数の形を持っているこれらの例では、それは最初の要素がオペレータ(または関数)と残りの要素であるリストとして書かれた式で、あるオペランドを(これは「プレフィックス表記法」と呼ばれる、または「ポーランド記法されています")。 REPLにフォームを書くと、その評価が行われます。この例では、引数が定数、文字列、記号(型の名前である'string
の場合)である単純式を見ることができます。また、算術演算子は任意の数の引数を取ることができます。
括弧は構文の不可欠な部分であり、他のプログラミング言語のように自由に使用することはできないことに注意することが重要です。たとえば、次のようなエラーがあります。
(+ 5 ((+ 2 4)))
> Error: Car of ((+ 2 4)) is not a function name or lambda-expression. ...
Common Lispでは、フォームはデータ、シンボル、マクロフォーム、特殊フォーム、ラムダフォームでもあります。それらは評価されるように書くことができ、ゼロ、1つ、またはそれ以上の値を返したり、マクロに入力して他の形式で変換することができます。
整数のリストの合計
(defun sum-list-integers (list)
(reduce '+ list))
; 10
(sum-list-integers '(1 2 3 4))
; 55
(sum-list-integers '(1 2 3 4 5 6 7 8 9 10))
ラムダ式と無名関数
無名関数は、 ラムダ式で名前なしで定義することができます。これらのタイプの関数を定義するには、キーワードdefun
代わりにキーワードlambda
が使用されます。次の行はすべて同等であり、2つの数値の合計を出力する無名関数を定義します。
(lambda (x y) (+ x y))
(function (lambda (x y) (+ x y)))
#'(lambda (x y) (+ x y))
それらの有用性は、 ラムダフォームを作成する際に顕著です。つまり、最初の要素がラムダ式であり、残りの要素が無名関数の引数である形式のフォームです 。例( オンライン実行 ):
(print ((lambda (x y) (+ x y)) 1 2)) ; >> 3
(print (mapcar (lambda (x y) (+ x y)) '(1 2 3) '(2 -5 0))) ; >> (3 -3 3)
Common Lisp学習リソース
オンライン書籍
これらはオンラインで自由にアクセスできる本です。
- Peter SeibelのPractical Common Lispは経験豊富なプログラマーのためのCLの紹介であり、CLを他の言語とどのように異ならせるかを最初から強調しています。
- コモン・リスプ(Common Lisp):シンボリック・コンピューティングへの穏やかな紹介David S. Touretzkyは、プログラミングを初めて学んだ人にとっては良い紹介です。
- Common Lisp:Stuart C. Shapiroによるインタラクティブなアプローチが講座の教科書として使用され、コースノートがウェブサイトの本に付属しています。
- Common Lisp、Guy L. Steeleの言葉はCommon Lisp言語の記述です。 CLikiによると、古くなっていますが、Common Lisp Hyperspecよりもループマクロとフォーマットのより良い記述が含まれています。
- Paul GrahamによるLispについては、中級者のLispersにとって素晴らしい本です。
- Doug HoyteによるLambdaは、Lispマクロに関する先進的な本です。 いくつかの人々は 、この本を読む前にあなたがOn Lispに慣れていること、そして開始が遅いことを勧めました。
オンライン参考文献
- Common Lisp HyperspecはCommon Lisp の言語リファレンスドキュメントです。
- Common Lisp Cookbookは、便利なLispのレシピのリストです。 CL情報の他のオンラインソースのリストも含まれています。
- Common Lisp Quick Referenceには、印刷可能なLispリファレンスシートがあります。
- Lispdoc.comは、ドキュメントのために、いくつかのLisp情報ソース(Practical Common Lisp、Successful Lisp、On Lisp、HyperSpec)を検索します。
- L1sp.orgはドキュメントのリダイレクトサービスです。
オフライン書籍
あなたが購入しなければならない、または図書館から貸し出される可能性のある書籍です。
- Paul GrahamによるANSI Common Lisp
- Edmund WeitzさんによるCommon Lisp Recipes
- 人工知能のパラダイムプログラミングはLispの多くの興味深いアプリケーションを持っていますが、AIのこれ以上の参考にはなりません。
オンラインコミュニティ
- CLikiには素晴らしいスタートアップページがあります。すべてのものCLのための素晴らしいリソース。 Lispの本の広範なリストを持っています。
- Common Lisp subredditには、サイドバーに便利なリンクと参照ドキュメントがたくさんあります。
- IRC:#lisp、#ccl、#sbclと他人にあるFreenode 。
- Common-Lisp.netは、多くの一般的なlispプロジェクトとユーザグループをホストしています。
図書館
- QuicklispはCommon Lispのライブラリマネージャであり、サポートされているライブラリのリストが長い。
- Quickdocsは、多くのCLライブラリのライブラリドキュメントを提供しています。
- Awesome CLは、カテゴリ別に分類された図書館、フレームワーク、および他の光沢のあるもののコミュニティ主導型のキュレーションリストです。
あらかじめパッケージ化されたLisp環境
これらは、必要なものすべてがあらかじめパッケージ化され、事前に設定されているため、インストールが簡単で使い始めやすいLisp編集環境です。
- PortacleはポータブルでマルチプラットフォームのCommon Lisp環境です。スライム、SBCL(一般的なCommon Lispの実装)、Quicklisp、Gitを使って、ややカスタマイズされたEmacsを提供しています。インストールは必要ありませんので、非常に簡単で簡単な方法です。
- Lispboxは、Windows、Mac OSX、Linux用のアーカイブとしてあらかじめパッケージ化されたIDE(Emacs + SLIME)、Common Lisp環境(Clozure Common Lisp)、ライブラリマネージャ(Quicklisp)です。 "Lisp in a Box"の後継です。実用的なCommon Lispの本でお勧めします。
- あらかじめパックされていませんが、 SLIMEはEmacsをCommon Lisp IDEに変え、 使い始める手助けをするユーザマニュアルを持っています 。個別のCommon Lisp実装が必要です。
Common Lispの実装
このセクションでは、いくつかの一般的なCL実装とそのマニュアルを示します。特記のない限り、これらはフリーソフトウェアの実装です。 ClikiのフリーソフトウェアCommon Lisp実装 のリスト 、およびWikipediaの商用Common Lisp実装 のリストも参照してください。
- Allegro Common Lisp(ACL)とマニュアル 。商用ですが、YouTubeには無料のExpress Editionとトレーニングビデオがあります。
- CLISPとマニュアル 。
- Clozure Common Lisp(CCL)とマニュアル 。
- Carnegie Mellon University Common Lisp(CMUCL)には、 マニュアルやその他の有用な情報ページがあります。
- 埋め込み可能なCommon Lisp(ECL)とマニュアル 。
- LispWorksとマニュアル 。商用だが、 いくつかの制限があるPersonal Editionがある 。
- Steel Bank Common Lisp(SBCL)とマニュアル 。
- Scieneer Common Lisp(SCL)とマニュアルは商用LinuxとUnixの実装ですが、 無制限の評価と非商用バージョンがあります。