The Common Lisp Cookbook – Common Lisp を始める

Table of Contents

The Common Lisp Cookbook – Common Lisp を始める

📢 🎓 ⭐ Learn Common Lisp efficiently in videos, by the Cookbook's main contributor. Learn more.

🖊️ Discover a new Common Lisp and Coalton editor for beginners: mine and a new VSCode extension for Common Lisp: OLIVE.

開発環境をインストールし、新しい Common Lisp プロジェクトを始めるための簡単な手順から始めます。

実装をインストールする

パッケージマネージャを使う

どの Common Lisp 実装を使えばよいかわからない場合は、SBCL を試してください。

apt-get install sbcl

Common Lisp は ANSI 標準ですが、実装が標準に加えて提供する機能は大きく異なることがあります。Wikipedia の実装一覧を参照してください。

次の実装は Debian と、ほとんどの主要な Linux ディストリビューション向けにパッケージ化されています。

その他のよく知られた実装には次のものがあります。

また、古い実装として次のものがあります。

macOS の場合

homebrew を使って SBCL をインストールします。

brew install sbcl

Homebrew で Emacs エディタをインストールすることもできますが、Common Lisp を使うために必須ではありません。ターミナルで SBCL を使う方法は後述します。また、Editor Support の節も参照してください。

brew tap d12frosted/emacs-plus
brew install emacs-plus

Windows の場合

上記のすべての実装は Windows にインストールできます。

SBCL は Chocolatey で入手できますが、これは公式のインストール方法ではありません。

> choco install sbcl

plain-common-lisp も使えます。これは Windows 上でネイティブな Common Lisp 環境を得るための簡単な方法です。Emacs と Slime、Quicklisp、SBCL を数クリックでインストールできます。ワークスペース内でアーカイブを展開するだけです。

または、Emacs を自分でインストールして設定することもできます。

> choco install emacs

Docker を使う

すでに Docker を知っているなら、Common Lisp をかなり素早く始められます。clfoundation/cl-devel イメージには、最近の SBCL、CCL、ECL、ABCL に加えて、ホームディレクトリ(/home/cl)にインストール済みの Quicklisp が含まれているので、すぐにライブラリを ql:quickload できます。

Docker は GNU/Linux、Mac、Windows で動作します。

次のコマンドは必要なイメージ(圧縮状態で約 1.0GB)をダウンロードし、指定した場所にローカルのソースを Docker イメージ内へ入れ、SBCL REPL に入ります。

docker run --rm -it -v /path/to/local/code:/home/cl/common-lisp/source clfoundation/cl-devel:latest sbcl

それでも Emacs と SLIME を使って開発したいので、SLIME を Docker 内の Lisp に接続する必要があります。その設定を助けるライブラリである slime-docker を参照してください。

asdf-vm パッケージマネージャを使う

asdf-vm ツールは、大きなランタイムとツールのエコシステムを管理するために使えます。

Steel Bank Common Lisp (SBCL)asdf-sbcl plugin 経由で利用できます。

次のようにインストールします。

asdf plugin-add sbcl https://github.com/smashedtoatoms/asdf-sbcl.git

Roswell を使う

Roswell は、次のような Common Lisp ツールです。

インストール方法はいくつかあり、wiki で見つかります(Debian パッケージ、Windows インストーラ、Brew/Linux Brew など)。

REPL を起動する

コマンドラインで実装の実行ファイルを起動するだけで、REPL(Read Eval Print Loop)、つまり対話的インタプリタに入れます。

終了するには (quit) または ctr-d を使います(一部の実装)。

サンプルセッションを示します。sbcl バイナリを起動し、起動メッセージが表示され、Lisp プロンプト(* )に入り、lisp フォームを入力し、その後終了します。

user@debian:~$ sbcl
This is SBCL 2.1.11.debian, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
* (+ 1 2)

3
* (quit)
user@debian:~$

ファイルをロード、再ロードする

REPL で Lisp コードを評価しました。おめでとうございます。もちろん、コードは .lisp ファイルに書きたくなるでしょう。

sbcl --load myfile.lisp を使うと、このファイルをロード、コンパイル、実行できます。トップレベルのコマンドが実行された後も Lisp プロセスは終了せず、REPL が表示されるので、作業を続けられます。

.lisp ファイルを編集した後、終了して SBCL コマンドを再び呼び出してファイルを --load する必要はありません。REPL 内から単に load できます。

$ sbcl --load myfile.lisp

a… bunch… of… awesome… stuff

* (load "myfile.lisp")

この * の部分に気づきましたか。これはターミナルでのデフォルトの Lisp プロンプトです。エディタ内では通常、現在のパッケージを示す CL-USER> が表示されます。

エディタといえば、もちろん、よく設定されたエディタを使えば、はるかに対話的なワークフローを得られます。ただし、この方法でもすでに作業できます。

より使いやすい REPL: rlwrap

少なくとも SBCL では、REPL はそのままだとあまり使いやすくありません。履歴(以前に入力したコマンド)を呼び出すための矢印キーが動かず、組み込み Lisp 関数の補完もありません。

rlwrap をインストールして使うことで、機能を少し強化できます。

オペレーティングシステム コマンド
Linux (Debian) apt-get install rlwrap
macOS brew install rlwrap
Windows choco install rlwrap

次のように起動します。

rlwrap sbcl

これにより、素のターミナル REPL にある程度の使い勝手が加わります。ただし、このようなターミナル REPL で作業するかわりに、もっとよい編集体験を提供するようエディタを設定します。editor-support を参照してください。

TIP: CLISP 実装は、ターミナル向けによりよいデフォルト REPL を持っています(readline 機能、シンボル補完)。clisp -on-error abort を使えば、デバッガなしでエラーメッセージを得ることもできます。ちょっと試すには便利ですが、エディタを設定し、SBCL または CCL を使うことをおすすめします。
TIP: rlwrap に -c スイッチを追加すると、ファイル名を自動補完できます。

より使いやすい REPL: ICL

ICL、Interactive Common Lisp は、ターミナル向けの拡張 REPL です。システム上にあるどの実装でも動作します。多くの便利な機能をもたらします。よいエディタの代わりにはなりませんが、実際にそれを補完できます。

ICL は次を提供します。

ICL は初心者にもやさしいことにも注意してください。対話的デバッガを持ちません。その代わり、どんなエラーも処理し、エラーメッセージを表示し、プログラマが ,bt コマンドでバックトレースを見られるようにします。

GNU/Linux ではビルド済みバイナリとパッケージ(.deb、.rpm)で、Windows では zip、exe、MSI インストーラでインストールできます。GitHub releases を参照してください。ビルドも簡単です。

icl がパス上にあるなら、起動します。

$ icl
COMMON-LISP-USER>

REPL を起動する前に、--load / -l オプションでファイルを load することもできます。

$ icl -l mycode.lisp
your… output…
COMMON-LISP-USER> (your-function-is-available)

楽しんでください。

類似のプロジェクトに cl-repl があります。エディタの節を参照してください。

ICL は LLM の助けを借りてコーディングされたプロジェクトです。

対話的デバッガ

Lisp は本質的に対話的なので、エラーが起きた場合はデバッガに入ります。場合によってはこれが煩わしいこともあるため、SBCL の --disable-debugger オプションを使いたくなるかもしれません。

また、上で見た icl は対話的デバッガを持たず、エラーメッセージを表示し、バックトレースを表示できるようにする点にも注意してください。

ライブラリ

Common Lisp には、フリーソフトウェアライセンスの下で利用できる何千ものライブラリがあります。次を参照してください。

用語

Quicklisp をインストールする

Quicklisp は単なるパッケージマネージャではありません。すべてのライブラリが一緒にビルドできることを保証する中央リポジトリ(dist)でもあります。

SEE ALSO: 新しい OCICL パッケージマネージャも参照してください。コマンドラインツールを提供し、プロジェクトローカルの依存関係で動作し(詳細は後述)、デフォルトで HTTPS を使い、Quicklisp から独立したリポジトリです。

Quicklisp は独自の dist を提供しますが、自分たちで構築することも可能です。

インストールするには、次のどちらかを行います。

1- 任意の場所でこのコマンドを実行します。

curl -O https://beta.quicklisp.org/quicklisp.lisp

そして Lisp REPL に入り、このファイルをロードします。

sbcl --load quicklisp.lisp

または

2- Debian パッケージをインストールします。

apt-get install cl-quicklisp

そして REPL からロードします。

(load "/usr/share/common-lisp/source/quicklisp/quicklisp.lisp")

次に、どちらの場合も、引き続き REPL から実行します。

(quicklisp-quickstart:install)

これにより ~/quicklisp/ ディレクトリが作成され、Quicklisp はそこで状態とダウンロードしたプロジェクトを管理します。

必要なら、Quicklisp を別の場所へインストールできます。たとえば Unix システムで隠しフォルダへインストールするには次のようにします。

;; optional
(quicklisp-quickstart:install :path "~/.quicklisp")

最後に、新しい Lisp セッションを開始するたびに常に Quicklisp をロードするには、次を実行します。

(ql:add-to-init-file)

これは CL 実装の init ファイルへ適切な内容を追加します。そうしない場合、Quicklisp や Quicklisp 経由でインストールしたライブラリを使いたいすべてのセッションで、(load "~/quicklisp/setup.lisp") を実行する必要があります。

たとえば ~/.sbclrc には次の内容が追加されます。

#-quicklisp
  (let ((quicklisp-init (merge-pathnames
                          "quicklisp/setup.lisp"
                          (user-homedir-pathname))))
    (when (probe-file quicklisp-init)
      (load quicklisp-init)))

ライブラリをインストールする

REPL で次を実行します。

(ql:quickload "system-name")

たとえば、これは文字列操作ライブラリ “str” をインストールします。

(ql:quickload "str")

以上です。すぐに使えます。

(str:title-case "HELLO LISP!")
SEE MORE: package:a-symbol 記法を理解するには、packages page の "Accessing symbols from a package" 節を読んでください。

一度に複数のライブラリをインストールできます。ここでは、正規表現用の cl-ppcre と、ユーティリティライブラリである Alexandria をインストールします。

(ql:quickload '("str" "cl-ppcre" "alexandria"))

Lisp REPL でサードパーティライブラリを使いたいときはいつでも、この ql:quickload コマンドを実行できます。そのライブラリがすでにファイルシステム上にインストールされていることがわかれば、2回目はネットワークにアクセスしません。ライブラリはデフォルトで ~/quicklisp/dists/quicklisp/ にインストールされます。

また、多数の Common Lisp ライブラリが Debian でパッケージ化されていることにも注意してください。パッケージ名は通常 cl- prefix で始まります(すべてを一覧するには apt-cache search --names-only "^cl-.*" を使います)。

たとえば cl-ppcre ライブラリを使うには、まず cl-ppcre パッケージをインストールする必要があります。

次に、SBCL では次のように使えます。

(require "asdf")
(require "cl-ppcre")
(cl-ppcre:regex-replace "fo+" "foo bar" "frob")

ここでは Quicklisp がインストールされていないふりをして、ファイルシステム上で利用できるモジュールを require でロードしています。迷ったら ql:quickload を使えます。

その他のコマンドについては Quicklisp のドキュメントを参照してください。たとえば Quicklisp のディストリビューションをアップグレードまたはロールバックする方法を見てください。

高度な依存関係管理

Common Lisp プロジェクトは、次のどのフォルダにも置けます。

ここにインストールされたライブラリは、すべてのプロジェクトで自動的に利用可能になります。

完全な一覧については、次の値を参照してください。

(asdf/source-registry:default-user-source-registry)

および

asdf:*central-registry*

*central-registry*asdf package 内のトップレベル変数で、いわゆる “*earmuffs*” を使って書かれています。これは便利な慣習です。Variables 章を参照してください。

ライブラリの自分用バージョンを用意する。プロジェクトを clone する。

上記の性質により、任意のライブラリを ~/quicklisp/local-projects/ ディレクトリへ clone すれば、それは ASDF(および Quicklisp)に見つけられ、すぐに利用可能になります。

(asdf:load-system "system")

または

(ql:quickload "system")

両者の実用上の違いは、ql:quickload は system がまだインストールされていない場合、まずインターネットから取得しようとすることです。

local-projects 内のシンボリックリンクが、好みの別の場所を指していても動作することに注意してください。

プロジェクトローカルなライブラリバージョンを扱う方法

ライブラリを1つのプロジェクトだけのためにローカルへインストールする必要がある場合、または依存関係リストをアプリケーションと一緒に簡単に配布したい場合は、Qlot または ocicl を使えます。

どちらのプロジェクトもコマンドラインツールを提供し、ロックファイル(qlfile.lockocicl.csv)で依存関係を固定でき、グローバルな Quicklisp インストールに触れずに依存関係をローカルへインストールして管理するコマンド(qlot installocicl install)を提供します。

もちろん、ほかのエコシステムで主流になっている依存関係管理スタイル、つまり npmpip などを思い浮かべているでしょう。しかし、これらのツールをここで紹介しているのは、Common Lisp ではそれほど必要になることが少ないからです。

NOTE: 初心者はまだプロジェクトローカルな依存関係について心配する必要はありません。グローバルな Quicklisp 依存関係と quicklisp/local-projects/ だけでかなり先まで進めます。自分にとって最も簡単なツールを選んでください(きっと Quicklisp です)。

理由は少なくとも2つあります。まず、言語(およびその実装)は非常に安定しています。たとえば実装が lisp syntax の破壊的変更を導入することは決してありません。ときどき小さな破壊的変更が入りますが、それに気づくのはかなり熱心なユーザーだけです。次に、エコシステムも非常に安定しており、通常、ライブラリ作者は安定性のルールに従います。非推奨警告が 12(十二)年残り続けているのを見たことがあります。全体として、Common Lisp の世界の初心者は、プロジェクトローカルな依存関係について、それほど、あるいはまったく心配する必要がありません。

この用途のための別のツールもいくつか挙げておきます。

Quicklisp は Quicklisp bundles も提供しています。これは Quicklisp からエクスポートされ、Quicklisp を介さずにロードできる、自己完結した system の集合です。

最後に、dist の構築を助ける Quicklisp controller があります。

プロジェクトで作業する

Quicklisp とエディタの準備ができたので、ファイルに Lisp コードを書き、REPL と対話し始められます。

しかし、既存のプロジェクトで作業したい、または新しいプロジェクトを作成したい場合は、どう進めればよいのでしょうか。defpackage の正しい順序は何でしょうか。.asd ファイルには何を書くべきでしょうか。プロジェクトを REPL にロードするにはどうすればよいでしょうか。

新しいプロジェクトを作成する

プロジェクト構造のひな形作成を助けるプロジェクトビルダがあります。ここでは cl-project を好んで使います。これはテストの骨組みも設定します。

要するに次のとおりです。

(ql:quickload "cl-project")
(cl-project:make-project #P"./path-to-project/root/")

これは次のようなディレクトリ構造を作成します。

|-- my-project.asd
|-- my-project-test.asd
|-- README.markdown
|-- README.org
|-- src
|   `-- my-project.lisp
`-- tests
    `-- my-project.lisp

ここで my-project.asd は次のようになります。

(asdf:defsystem "my-project"
  :version "0.1.0"
  :author ""
  :license ""
  :depends-on ()  ;; <== list of Quicklisp dependencies
  :components ((:module "src"
                :components
                ((:file "my-project"))))
  :description ""
  :long-description
  #.(read-file-string
     (subpathname *load-pathname* "README.markdown"))
  :in-order-to ((test-op (test-op "my-project-test"))))

そして src/my-project.lisp は次のようになります。

(defpackage footest
  (:use :cl))
(in-package :footest)

既存のプロジェクトをロードする方法

新しいプロジェクトを作成した、または既存のプロジェクトがあり、それを REPL で扱いたい。しかし Quicklisp はそれを知りません。どうすればよいでしょうか。

まず、~/common-lisp~/.local/share/common-lisp/source/~/quicklisp/local-projects のいずれかに作成または clone すれば、追加の手間なしで (ql:quickload …) できます。

そうでない場合は、先に system 定義(.asd)をコンパイルしてロードする必要があります。SLIME で slime-asdf contrib がロードされているなら、.asd 内で C-c C-kslime-compile-and-load-file)を入力し、その後 (ql:quickload …) できます。

C-c C-k の代わりに、プログラムから (asdf:load-asd "my-project.asd") を使うこともできます。

通常、この段階で REPL 内で system に「入る」ことになります。

(in-package :my-project)

最後に、ソース(my-project.lisp)を C-c C-k でコンパイルするか、フォーム内で C-c C-cslime-compile-defun)により eval して、その結果を REPL で確認できます。

もう1つの解決策は、ASDF の既知プロジェクト一覧を使うことです。

;; startup file like ~/.sbclrc
(pushnew "~/to/project/" asdf:*central-registry* :test #'equal)

ASDF は Quicklisp に統合されているので、すぐに自分のプロジェクトを quickload できます。

Happy hacking !

追加設定

SBCL のデフォルトエンコーディング形式を utf-8 に設定したくなるかもしれません。

(setf sb-impl::*default-external-format* :utf-8)

これは ~/.sbclrc に追加できます。

REPL がすべてのシンボルを大文字で表示するのが嫌なら、次を追加します。

(setf *print-case* :downcase)
Warning: これは、一部のパッケージの動作を壊す可能性があります。実際に Mito で起きました。本番では避けてください。

関連項目

クレジット

Page source: ja/getting-started.md

T
O
C