Hash-table in elisp
まず skk 辞書フォーマットを処理するためのマクロ with-skk-jisyo-buffer と、
skk-large-jisyo ファイルを処理するためのマクロ with-skk-large-jisyo とを定義する。
(defmacro with-skk-jisyo-buffer (buffer key value &rest body) `(with-current-buffer ,buffer (goto-char (point-min)) (while (not (eobp)) (beginning-of-line) (if (looking-at "^;") nil (if (looking-at "\\(^[^ ]+\\) \\(.*\\)$") (let ((,key (match-string-no-properties 1)) (,value (match-string-no-properties 2))) ,@body))) (forward-line)))) (defmacro with-skk-large-jisyo (key value &rest body) (let ((buf (make-symbol "tmpbuf"))) `(let ((,buf (skk-get-jisyo-buffer skk-large-jisyo t))) (with-skk-jisyo-buffer ,buf ,key ,value ,@body))))
こうしておくと、 Emacs Lisp 組み込みのハッシュテーブルに skk-large-jisyo を読み込む関数は以下のようにシンプルになる。
(defun skk-jisyo-hash () (let ((ht (make-hash-table :test 'equal))) (with-skk-large-jisyo k v (puthash k v ht)) ht))
これで elisp で実装したハッシュテーブルと簡単に比較できるようになった。elisp 版はこんな感じ。
(defun skk-jisyo-el-hash () (let ((table (my-make-hash-table 15000))) (with-skk-large-jisyo k v (my-puthash k v table)) table))
my-make-hash-table, my-puthash などは elisp によるハッシュテーブルの実装で、まずはこんな風に書いてみた。
vector を使い、その要素は alist にしている。よって、ハッシュ関数によってベクトルの指定の位置まで飛び、その後 alist で検索する。
;; hash table in elisp (defun my-make-hash-table (&optional length) (make-vector (or length 64) nil)) (defun my-sxhash (table key) (abs (% (sxhash key) (length table)))) (defun my-puthash (key value table) (let ((h (my-sxhash table key))) (let ((lst (aref table h))) (setf (aref table h) (acons key value (if (assoc key lst) (remove (assoc key lst) lst) lst)))) table)) (defun my-gethash (key table &optional dflt) (let ((hash (my-sxhash table key))) (let ((lst (aref table hash))) (if (assoc key lst) (cdr (assoc key lst)) dflt))))