kikkiiのブログ

ひきこもり

common lispのハッシュテーブルは使いにくい

ハッシュテーブルという言葉を最初に見たとき、難しそうで私は怯えた。でも、ハッシュテーブルがkeyの対を詰め込む辞書マップのようなものだと分かったとき、使う分には「なんだそんなことか割と簡単だ」と思った。でも、common lispでハッシュテーブルを使おうとすると、面倒なのでやる気がなくなってくる。

;; hhhという名前のハッシュテーブルをつくる
(defparameter hhh (make-hash-table))

;; hhhに:key1というキーと値111を入れる
(setf (gethash :key1 hhh) 111)

;; hhhに入っている:key1の値を取り出す
(gethash :key1 hhh)
111
T

;; まとめて入れる
(setf (gethash :key2 hhh) 222
      (gethash 'key3 hhh) 333
      (gethash "key4" hhh) 444)

;; 取り出す
(gethash :key2 hhh)
222
T

(gethash 'key3 hhh)
333
T

;; あれ...
(gethash "key4" hhh)
NIL
NIL

最後の(gethash "key4" hhh)で値が取り出せないのは、キーに文字列を使ったからだ。 文字列をキーとして使いたい場合は、ハッシュテーブルをつくるとき次のようにしなければなかった。

(defparameter hhh (make-hash-table :test #'equalp))

;; ハッシュテーブルにキーと値を入れる
(setf (gethash "key4" hhh) 444)

;; 値を取り出す
(gethash "key4" hhh)
444
T

嫌になってくる。でも、serapeumというパッケージの中で、このごたごたを解決するいいもの(dictとdict*)を見つけた。

(ql:quickload :serapeum)

;; hhhという名前のハッシュテーブルをつくり、まとめてキーと値を入れる
(defparameter hhh (serapeum:dict :key1 111
                                 :key2 222
                                 'key3 333
                                 "key4" 444))

(gethash :key1 hhh)
111
T

(gethash :key2 hhh)
222
T

(gethash 'key3 hhh)
333
T

(gethash "key4" hhh)
444
T

;; hhhに追加でキーと値を入れる
(serapeum:dict* hhh "key5" 555)

(gethash "key5" hhh)
555
T

dictを使えば、キーと値を交互に並べて属性リストっぽく書けばハッシュテーブルがつくれるのでよい。