Macro WITH-PACKAGE-ITERATOR
with-package-iterator
(name package-list-form &rest
symbol-types) declaration* form*
=> result*
name - シンボル
package-list-form - フォーム。いちど評価されてpackage-listを生成します。
package-list - パッケージ指定子のリストの指定子
symbol-types - 次のシンボルのうちの一つ、:internal
, :external
, :inherited
。
declaration - 宣言式。評価されません。
form - 暗黙のprogn
result - formの返却値
formのボディ部のレキシカルスコープ内で nameがmacrolet
によって定義され、 (name)
が連続して呼び出されたときに、 package-listのパッケージからシンボルがひとつずつ返却されます。
パッケージが複数継承されていたもののシンボルが 一度ではなく複数にわたって返却されるかどうかは指定されていません。 返却されるシンボルの順番は、 package-listのパッケージの順番を反映する必要はありません。 もしpackage-listに複数の要素があったときは、 シンボルがひとつ返却されるか複数回返却されるかは指定されていません。
symbol-typesはパッケージのアクセス可能なシンボルに対して、 次のような返却の制御を行います。
:internal
export
ではありません。:external
export
の両方です。:inherited
use
されているパッケージの外部シンボルですが、 shadow
はされていないものです。symbol-typesにひとつ以上の引数が指定されたときは、 シンボルのアクセスが指定された symbol-typesのうちのどれかにマッチするものが返却されます。 実装はこの構文に追加で認識可能なシンボルのアクセス型を 拡張するかもしれません。
(name)
の起動は、下記のような4つの値を返却します。
:internal
, :external
, :inherited
。(name)
の連続の呼び出しによって 全てのシンボルが返却されたあとは、 ただひとつの値であるnil
のみが返却されます。
返却値の第2、第3、第4の意味は、 以下で示される第2返却値の内容で、 返却されたシンボルが返却されたパッケージでアクセス可能ということです。
:internal
export
ではない。:external
export
されている。:inherited
shadow
でもない)が、 use
されたいくつかのパッケージから継承されている。呼び出しフォームを囲った何かのクロージャーを返すなどして、 with-package-iterator
フォームの動的エクステントの外で 繰り返しの暗黙の内部状態の何かが返却された場合には、 何が起こるは規定されていません。
with-package-iterator
はいくつでもネストすることができ、 それらの全てのマクロが違う名前を持つ場合は、 もっとも内側のボディ部では 確立されたすべてのローカルマクロを起動することができます。
下記の関数はどんなパッケージでもt
を返却し、 もしwith-package-iterator
の使用で 対応するdo-symbols
の使用が合意されなかったときは エラーが発生します。
defun test-package-iterator (package)
(unless (packagep package)
(setq package (find-package package)))
(let ((all-entries '())
(
(generated-entries '()))do-symbols (x package)
(multiple-value-bind (symbol accessibility)
(find-symbol (symbol-name x) package)
(push (list symbol accessibility) all-entries)))
(with-package-iterator (generator-fn package
(:external :inherited)
:internal loop
(multiple-value-bind (more? symbol accessibility pkg)
(
(generator-fn)unless more? (return))
(let ((l (multiple-value-list (find-symbol (symbol-name symbol)
(package))))
unless (equal l (list symbol accessibility))
(error "Symbol ~S not found as ~S in package ~A [~S]"
(symbol accessibility (package-name package) l))
push l generated-entries)))))
(unless (and (subsetp all-entries generated-entries :test #'equal)
(subsetp generated-entries all-entries :test #'equal))
(error "Generated entries and Do-Symbols entries don't correspond"))
(t))
下記の関数は全ての現れるシンボルを印刷します(複数回の可能性があります)。
defun print-all-symbols ()
(with-package-iterator (next-symbol (list-all-packages)
(:external)
:internal loop
(multiple-value-bind (more? symbol) (next-symbol)
(if more?
(print symbol)
(return)))))) (
なし。
なし。
symbol-typesが指定されなかったか、 symbol-typesのどれかが実装では認識できないものが指定されたときは、 with-package-iterator
は型program-error
のエラーを通知します。
with-package-iterator
によって確立された nameという名前のローカル関数が、 その主値がfalseを返却したあとで 呼び出されたときの結果は未定義です
3.6. 横断の規則と副作用
なし。