プログラミング::CommonLisp

12.1 プログラム・ファイル

フォームを保存しているファイルから,システムにフォームを入力する。
(load "ファイル名")
(load "ファイル名" :print t)
ファイルの中のフォームが評価される。
「:print t」を書けば,フォームが評価されるごとにその値が標準出力に出力される。
  • 例: foo.lisp
(defun 4jou (x &aux (y (* x x)))
  (* y y))

> (load "foo.lisp" :print t)
Loading foo.lisp
4jou
Finished loading foo.lisp
t

「Loading」とか「Finished」とかが邪魔なら
(load "foo.lisp" :verbose nil)
とか
(setq *load-verbose* nil)
とかする。

12.2 コンパイラ

例えば,関数barをコンパイルするには,
> (compile 'bar)
bar

ファイルをまるごとコンパイルするには,
(compile-file "入力ファイル名" :output-file "出力ファイル名")
> (compile-file "foo.lisp" :output-file "foo.out")
出力ファイルを実行するには,
> (load "foo.out")
出力ファイルをオブジェクトファイルという。
キーワードパラメータ :output-file を指定しないときは,
.fasl になる。(システムによる)

eval-when

コンパイラはソースファイルの中のフォームを次々にに読み込み,
これらのトップレベルのフォームを逐一変換していく。
この過程で読み込んだトップレベルフォームを評価することがある。
例えば defmacro式。コンパイル時にマクロ展開される。
プログラム実行時にマクロ展開すると効率が悪いため。
マクロ式以外にもあるがシステムによる。

もしコンパイル時に評価してほしいトップレベルフォーム(フォーム)があり,
コンパイラがこれを評価しない場合は,
そのフォームをスペシャルフォーム eval-when の中に入れて,
(eval-when (compile load eval) フォーム)
とする。
このトップレベルフォームをコンパイラが読むと,
フォームを先に評価し,その後で通常の変換をフォームに行う。
(compile load eval)
は評価時の指定で次の意味を持つ。
compile コンパイル時
load オブジェクトファイルのロード時
eval ソースファイルのロード時

12.3 モジュール構造

provide

プログラムが大きくなると,プログラム全体をいくつかの部分に分ける。(モジュール化)
プログラムがモジュールに分かれた場合,各モジュールに名前をつけておく。
(provide モジュール名)
ファイルの先頭にというフォームを書くと,
そのファイルが,モジュール名で宣言された名前のモジュールであるということになる。

ファイルの先頭に,
(provide 'kansai)
と書くと,このファイルが kansai というモジュールであることを宣言している。

provideが実行されると,
引数であるモジュール名が *modules* という変数に cons される。

require

provide と対になって使われる。
require はそれを実行したモジュールが
他のモジュールに依存することを表す。

kansai というモジュールの中に,
(require 'kanto)
という式があり,kansai モジュールを読み込んでいる途中で
(require 'kanto)
が実行されたとすると,
kanto というモジュールがその時点で読み込まれて入れば
(*modules* の値に入って入れば)何もしないが,
まだ読み込まれていなければ,
kanto というファイルが,kansai の残りを読み込む前に読み込まれる。
読み込むべきモジュールがいくつかのファイルに分かれていたり,
モジュールのあるファイルがモジュール名から類推できない時は,
require のモジュール名の後に,
ファイル名またはファイル名のリストを付け加える。
例えば,
(require 'kanto "azuma.lisp")
とする。


一般に,provide, require や,export, import, use-package などの
記号の読み込みに影響を与える関数はファイルの最初にまとめておくのが好ましい。
しかも次に示す順番が良いとされる。
  1. provide
  2. in-package
  3. shadow
  4. export
  5. require
  6. use-package
  7. import
  8. モジュールの中身(関数定義や変数宣言)

12.4 フィーチャ

組み込みのスペシャル変数 *features*

12.5 その他

describe と inspect は覚えておくと便利。
どちらも1つの引数をとる関数である。
引数はどんなデータでも良い。

describe

(describe 'cons)
とすると,consがlispパッケージの外部記号で,
consという関数が定義されており云々,ということが出力される。

inspect

describe はデータの情報を一度に出力するのにたいし,
inspect はユーザと対話しながら情報を提供してくれる。

apropos

(apropos 文字列)
とすると,文字列を印字名の一分とする全ての記号を表示してくれる。
同時に,個々の記号に関数関数定義や大域変数の値などの情報も表示してくれる。
関数名や変数名を忘れたときなどに便利である。
最終更新:2011年10月05日 11:09