Emacs Lisp Hash-Table C
Super Technique 講座
http://www.nurs.or.jp/~sug/soft/super/hash.htm を参考にしたら、
Elisp の Hash-Table も読めそうな気になってきたのでメモしていく。
Elisp の gethash は src/fns.c で定義されている。
ハッシュテーブルなので、任意のキーからハッシュ値を生成している部分があるはず。
コメントを付けてみる。
DEFUN ("gethash", Fgethash, Sgethash, 2, 3, 0, doc: /* Look up KEY in TABLE and return its associated value. If KEY is not found, return DFLT which defaults to nil. */) (key, table, dflt) Lisp_Object key, table, dflt; { /* Lisp Object がハッシュテーブルか確認して *h に設定 */ struct Lisp_Hash_Table *h = check_hash_table (table); /* ハッシュ値を取得 */ int i = hash_lookup (h, key, NULL); /* ヒットすれば値を、そうでなければ gethash の第3引数のデフォルト値を返す。*/ return i >= 0 ? HASH_VALUE (h, i) : dflt; }
puthash の方も見ると、やっぱり hash_lookup を呼んでいる。
src/fns.c を良く眺めてみると、 Hash Code Computation という部分があった。
怪しげなマジックナンバーが埋め込まれているので、
sxhash_string なる C の関数がハッシュ値を生成しているようだ。
勘が悪いことだが、ようやくElisp 側にも sxhash という関数があることに気づいた。
これがまず探していた、ハッシュ関数だ。
DEFUN ("sxhash", Fsxhash, Ssxhash, 1, 1, 0, doc: /* Compute a hash code for OBJ and return it as integer. */) (obj) Lisp_Object obj; { unsigned hash = sxhash (obj, 0);; return make_number (hash); }
本体は sxhash なる C 関数。任意の Lisp オブジェクトに対して、うまいことハッシュ値を計算しているだろうか?
型によって、sxhash_list とか sxhash_string を使い分けている。
list の場合は SXHASH_MAX_DEPTH より深くはたどらないようになっている。
HASH_VALUE は C のマクロで、ここで 「Lisp の配列」(※まだ実体がつかめていないが、
添字で高速にアクセスする対象。)から値を取り出しているらしい。
続く。