Macro WITH-PACKAGE-ITERATOR

UP


Macro WITH-PACKAGE-ITERATOR

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のボディ部のレキシカルスコープ内で namemacroletによって定義され、 (name)が連続して呼び出されたときに、 package-listのパッケージからシンボルがひとつずつ返却されます。

パッケージが複数継承されていたもののシンボルが 一度ではなく複数にわたって返却されるかどうかは指定されていません。 返却されるシンボルの順番は、 package-listのパッケージの順番を反映する必要はありません。 もしpackage-listに複数の要素があったときは、 シンボルがひとつ返却されるか複数回返却されるかは指定されていません。

symbol-typesはパッケージのアクセス可能なシンボルに対して、 次のような返却の制御を行います。

symbol-typesにひとつ以上の引数が指定されたときは、 シンボルのアクセスが指定された symbol-typesのうちのどれかにマッチするものが返却されます。 実装はこの構文に追加で認識可能なシンボルのアクセス型を 拡張するかもしれません。

(name)の起動は、下記のような4つの値を返却します。

  1. シンボルが返却されたかどうかを示すフラグ(trueならシンボルが返却された)。
  2. シンボルであり指定したパッケージのひとつからアクセスしたもの。
  3. シンボルのアクセスの型である次のどれか:internal, :external, :inherited
  4. パッケージであり、シンボルが得られた場所。 パッケージはpackage-list内にパッケージとして現れたものか あるいはその名前のひとつ。

(name)の連続の呼び出しによって 全てのシンボルが返却されたあとは、 ただひとつの値であるnilのみが返却されます。

返却値の第2、第3、第4の意味は、 以下で示される第2返却値の内容で、 返却されたシンボルが返却されたパッケージでアクセス可能ということです。

呼び出しフォームを囲った何かのクロージャーを返すなどして、 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 
                            :internal :external :inherited)
      (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)
                          :internal :external)
    (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. 横断の規則と副作用

備考

なし。


TOP, Github