Common Lispのハッシュテーブル

例によって、実践Common Lispを読みちゅう。11章でようやくリストの説明がはじまった。と思ったらまだだった。12章からみたい。著者としてはLispはリストだけじゃないんだよってことを言いたいらしい。

実践Common Lisp
実践Common Lisp
posted with amazlet at 09.04.09
Peter Seibel
オーム社
売り上げランキング: 199810

で、Common Lispのハッシュテーブルって。結構面倒かも?

CL-USER> (defparameter *hash* (make-hash-table)) ; ハッシュテーブル「*hash*」を作成
*HASH*
CL-USER> (setf (gethash 'apple *hash*) 100) ; *hash*にセット、「キー:apple, 値:100」
100
CL-USER> (setf (gethash 'orange *hash*) 250); 「キー:orange, 値:250」
250
CL-USER> (setf (gethash 'banana *hash*) 150); 「キー:banana, 値:150」
150
CL-USER> (setf (gethash 'strawberry *hash*) 380) ; 「キー:strawberry, 値:380」
380
CL-USER> (gethash 'orange *hash*) ; *hash*から「キー:orange」の値を取得
250
T

最後のgethashは分かるんだけど、ハッシュに値をセットするときが何か謎。一旦gethashで値をとりだしといて、それをセットするみたいな。どゆこと?

(setf *hash* 'key "value")

↑こんな感じでいけそうなのに。だめっすか。



とりあえずそれは置いといて、gethashの戻り値は複数ある(上の例だと250とTが返ってきてる)。これを多値というらしい(20章で詳しく説明するらしい)。特別な処理で2つ目の値を見ない限り2つ目は普段は無視される。2つの値を処理したい時はMULTIPLE-VALUE-BINDっ関数を使うんだって。こんな感じ↓。

CL-USER> (multiple-value-bind (key value)
	     (gethash 'strawberry *hash*)
	   (format t "key: ~a value: ~a" key value))
key: 380 value: TNIL

ほほう。しかし、戻り値がNILかどうかで判断するわけにはいかんのだろうか。

CL-USER> (gethash 'aaaa *hash*)
NIL
NIL

「*hash*」に定義されていないaaaaを指定したら1つ目にはNILだから値が入ってない場合の処理をしたいいから2つ目はいらないような・・・。
あ、aaaaがNILで設定されてるかも知れないからか。

CL-USER> (setf (gethash 'aaaa *hash*) NIL)
NIL
CL-USER> (gethash 'aaaa *hash*)
NIL
T

ほほう。2つ目の戻り値は指定したキーが設定されてるかどうかってことか。