Macro WITH-HASH-TABLE-ITERATOR
with-hash-table-iterator
(name hash-table) declaration* form* => result*
name - macrolet
の最初の引数として適切な名前
hash-table - フォーム。 一度だけ評価され、ハッシュテーブルを生成しなければなりません。
declaration - 宣言式。評価されません。
form - 暗黙のprogn
result - formの返却値
ボディ部のレキシカルスコープ内で nameがmacrolet
によって定義され、 連続した(name)
の実行は、 ハッシュテーブルからの要素がひとつひとつ返却されます。 ハッシュテーブルはhash-tableが一度だけ評価されることによって得られます。
(name)
の実行は、下記に示す3つの値が返却されます。
連続した(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 '())list nil)))
(unique (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. 横断の規則と副作用
なし。