Common Lisp
Common Lisp ハンドブック
[編集]Common Lisp は、多様なプログラミングスタイルをサポートする汎用プログラミング言語であり、主にAI研究や複雑なシステムの開発に用いられます。本ハンドブックでは、Common Lispの基本的な文法から応用的なトピックまでを体系的に解説します。
目次
[編集]Common Lisp概要
[編集]Common Lispは、1984年に標準化されたLispファミリーの一言語であり、高度な抽象化能力と動的な性質を持つ強力な言語です。以下の特徴を備えています。
- マルチパラダイムのサポート(手続き型、関数型、オブジェクト指向)
- 動的型付けと強力なREPL(Read-Eval-Print Loop)
- マクロシステムによる言語拡張
- 高い移植性と標準ライブラリ
環境のセットアップ
[編集]Common Lispを使い始めるには、適切な実装とツールをインストールする必要があります。
推奨実装
[編集]以下の実装が広く利用されています。
- SBCL (Steel Bank Common Lisp): 高速で広く支持される実装。
- CLISP: 軽量で移植性の高い実装。
- ECL (Embeddable Common Lisp): 他のアプリケーションと統合しやすい実装。
エディタと開発環境
[編集]- SLIME: Emacs向けの統合開発環境。
- VS Code: vscode-lisp拡張を使用可能。
- LispWorks: 商用の統合開発環境。
基本文法
[編集]式と評価
[編集]Common Lispでは、すべてのコードは式(S式)として記述されます。式はリストで構成され、関数呼び出しやデータ表現に使用されます。
;; 足し算の例 (+ 1 2 3) ;=> 6 ;; ネストした式 (* (+ 2 3) 4) ;=> 20
変数定義
[編集]変数はdefvar
またはsetq
を使って定義します。
;; グローバル変数の定義 (defvar *x* 10) ;; 変数の再代入 (setq *x* 20)
データ構造
[編集]Common Lispには、多様なデータ構造が用意されています。
リスト
[編集]リストはLispの基本的なデータ構造です。
;; リストの作成 (setq my-list '(1 2 3 4)) ;; 要素の追加 (push 0 my-list) ;=> (0 1 2 3 4) ;; 要素の削除 (pop my-list) ;=> 0
配列
[編集]配列(ベクトル)は、固定長のデータ構造です。
;; 配列の作成 (setq my-array #(1 2 3 4)) ;; 要素へのアクセス (aref my-array 2) ;=> 3 ;; 要素の更新 (setf (aref my-array 2) 42)
関数とマクロ
[編集]関数定義
[編集]defun
を使って関数を定義します。
(defun add (a b) (+ a b)) ;; 関数の呼び出し (add 2 3) ;=> 5
マクロ定義
[編集]マクロは、コードを生成するための仕組みです。
(defmacro when (condition &body body) `(if ,condition (progn ,@body))) ;; マクロの使用 (when t (print "Hello, world!"))
オブジェクト指向プログラミング
[編集]Common Lispは、CLOS(Common Lisp Object System)を通じて強力なオブジェクト指向プログラミングをサポートします。
;; クラスの定義 (defclass person () ((name :initarg :name :accessor person-name) (age :initarg :age :accessor person-age))) ;; オブジェクトの生成 (setq john (make-instance 'person :name "John" :age 30)) ;; アクセサの使用 (person-name john) ;=> "John" (setf (person-age john) 31)
エラー処理とデバッグ
[編集]エラー処理にはhandler-case
やrestart-case
を使用します。
(handler-case (/ 1 0) (division-by-zero () (print "Division by zero occurred.")))
並列処理
[編集]並列処理は、実装に依存しますが、Bordeaux Threadsなどのライブラリを利用すると簡単に実現できます。
外部ライブラリの利用
[編集]Quicklispを使って外部ライブラリを簡単にインストール・利用できます。
;; Quicklispのロード (ql:quickload "alexandria") ;; ライブラリの利用 (alexandria:flatten '((1 2) (3 4))) ;=> (1 2 3 4)
応用例
[編集]簡易Webサーバー
[編集]以下は簡単なHTTPサーバーの例です。
(ql:quickload "hunchentoot") (defparameter *my-server* (make-instance 'hunchentoot:easy-acceptor :port 8080)) (hunchentoot:start *my-server*) (format t "Server running on http://localhost:8080")
GUIアプリケーション
[編集]CLXやMcCLIMを利用して、GUIアプリケーションを作成できます。
Common Lispと他のLISP方言との差異
[編集]Common Lispは、SchemeやEmacs Lispなどの他のLISP方言と比較して、いくつかの重要な特徴を持っています。
1. 標準化と移植性
[編集]Common LispはANSIによって標準化されています。これにより、異なる実装間でのコードの移植性が高いという利点があります。他の方言は、標準が明確でない場合が多く、互換性が課題となることがあります。
2. データ型の豊富さ
[編集]Common Lispは、数値型、文字列、シーケンス、ハッシュテーブルなど、非常に多様なデータ型を備えています。これに対し、Schemeなどの方言では、データ型が最小限に抑えられている場合があります。
3. マクロシステム
[編集]Common Lispのマクロシステムは強力で、コード変換を自由に行うことができます。他の方言、特にSchemeでは、マクロがより単純化された形式で提供されています。
4. オブジェクト指向プログラミング
[編集]Common LispはCLOS (Common Lisp Object System) を備えており、強力なオブジェクト指向プログラミングの機能を提供します。他の方言では、オブジェクト指向機能が欠如しているか、限定的な実装に留まることがあります。
5. 実行環境の違い
[編集]Emacs Lispは主にEmacsのカスタマイズや拡張のために設計されていますが、Common Lispはより汎用的で、スタンドアロンアプリケーションや高度なアルゴリズム開発に適しています。