Lisp/基本からさらに一歩進んで/パッケージ

パッケージは Common Lisp における名前空間を分割する機能です。パッケージはパッケージの関数、マクロ、そして変数定義を他のシステムからの区別を可能にします。これにより名前衝突、つまり別々の人が違うものに同じ名前を使用して生じる、いくつもの問題を減らします。

シンボルは出力書式の PACKAGE-NAME::SYMBOL-NAME を持っています。しかし、もし PACKAGE-NAME のパッケージを使用していると、出力は SYMBOM-NAME を吐き出すだけです。動的変数 *PACKAGE* は常に現在使用しているパッケージを示します。パッケージの名前が ‘::’の記法で表示されているのでなければ、インターンされたとき、シンボルは *PACKAGE* の名前のパッケージにインターンされます。

パッケージは DEFPACKAGE で定義されます。パッケージでは PACKAGE-NAME:SYMBOL-NAME で命名された、言い換えれば一つの‘:’記号で命名されたようなケースの、パッケージのどのシンボルでも EXPORT してもかまいません。パッケージは他のパッケージからシンボルを IMPORT してもかまいません。もし、インポートされたシンボルが、すでにそのパッケージでインターンされた別のシンボルと同じ名前を持っていた場合、エラーが生じます。そこで一つのシンボルを選択しなければならなくなります。 USE-PACKAGE はパッケージから API を一つ選択してインポートするのに役立ちます。パッケージがエクスポートするシンボルと、パッケージが使用しているパッケージは DEFPACKAGE によって明示されます。

Example: パッケージの中の全てのシンボルのリスト

編集

Common Lisp ではパッケージのマクロを繰り返し処理するいくつものマクロが用意されています。最も関心を引くのは DO-SYMBOLS and DO-EXTERNAL-SYMBOLS です。 DO-SYMBOLS はパッケージの利用可能なシンボルをたどります。 DO-EXTERNAL-SYMBOLS は外部シンボルだけをたどります。(外部シンボルは実際のパッケージAPIとして見ることが出来ます)

たとえば "PACKAGE" という名前のパッケージのエクスポートされた全てのシンボルを出力するには、以下のように書くことが出来ます。

(do-external-symbols (s (find-package "PACKAGE"))
  (print s))

これらの全てのシンボルを list にまとめることもできます。

(let (symbols)
  (do-external-symbols (s (find-package "PACKAGE"))
    (push s symbols))
  symbols)

あるいは LOOP を使用しても記述することができます。

(loop for s being the external-symbols of (find-package "PACKAGE")
      collect s)

Copyright © 2002-2007 The Common Lisp Cookbook Project http://cl-cookbook.sourceforge.net/