Macro WITH-HASH-TABLE-ITERATOR

UP


Macro WITH-HASH-TABLE-ITERATOR

Macro WITH-HASH-TABLE-ITERATOR

構文

with-hash-table-iterator (name hash-table) declaration* form* => result*

引数と戻り値

name - macroletの最初の引数として適切な名前
hash-table - フォーム。 一度だけ評価され、ハッシュテーブルを生成しなければなりません。
declaration - 宣言式。評価されません。
form - 暗黙のprogn
result - formの返却値

定義

ボディ部のレキシカルスコープ内で namemacroletによって定義され、 連続した(name)の実行は、 ハッシュテーブルからの要素がひとつひとつ返却されます。 ハッシュテーブルはhash-tableが一度だけ評価されることによって得られます。

(name)の実行は、下記に示す3つの値が返却されます。

  1. エントリーが返却されたときにtrueを返すgeneralized-boolean
  2. hash-tableのエントリーのキー
  3. hash-tableのエントリーの値

連続した(name)の実行によって 全てのエントリーが返却された後は、 ただひとつだけの値nilが返却されます。

もし繰り返しの何らかの暗黙的な内部状態が クロージャーで起動フォームを囲んだ返却値などによって with-hash-table-iteratorフォームの 動的エクステントの外側で返却されたときに 何が起こるかは指定されていません。

with-hash-table-iteratorはいくつでもネストすることが可能であり、 もっとも内側のボディ部は、 これら全てのマクロが違う名前を持っているようなときは、 確立されたローカルマクロの全てを起動することができます。

例文

下記の関数はどんなハッシュテーブルでもtを返却し、 もしwith-hash-table-iteratorの使用が、 対応するmaphashの使用に合っていないときはエラーが発生します。

(defun test-hash-table-iterator (hash-table)
  (let ((all-entries '())
        (generated-entries '())
        (unique (list nil)))
    (maphash #'(lambda (key value) (push (list key value) all-entries))
             hash-table)
    (with-hash-table-iterator (generator-fn hash-table)
      (loop     
        (multiple-value-bind (more? key value) (generator-fn)
          (unless more? (return))
          (unless (eql value (gethash key hash-table unique))
            (error "Key ~S not found for value ~S" key value))
          (push (list key value) generated-entries))))
    (unless (= (length all-entries)
               (length generated-entries)
               (length (union all-entries generated-entries
                              :key #'car :test (hash-table-test hash-table))))
      (error "Generated entries and Maphash entries don't correspond"))
    t))

下記のものはwith-hash-table-iteratorによって実装された、 適切なmaphashの定義です。

(defun maphash (function hash-table)
  (with-hash-table-iterator (next-entry hash-table)
    (loop (multiple-value-bind (more key value) (next-entry)
            (unless more (return nil))
            (funcall function key value)))))

副作用

なし。

影響

なし。

例外

with-hash-table-iteratorによって確立された nameというローカル関数は、 それが第一返却値としてfalseを返却したあとに 呼び出された結果は未定義です。

参考

3.6. 横断の規則と副作用

備考

なし。


TOP, Github