連想リストふたたび、ふたたび

まだ9章4節。
id:yagiey:20090310:1236690209のデータベースから、値を取り出すための手続きを作ってみる。

(define item-properties
  (lambda (item)
    (cond
      ((assoc item *item-database*) => cdr)
      (else '()))))

(define item-property-get
  (lambda (action item)
    (cond
      ((assoc action (item-properties item)) => cdr)
      (else #f))))

まぁ、問題なし。
item-propertiesは、指定したアイテムの性質(つまり全ての属性)を取り出す手続き。
item-property-getは、指定したアイテムの指定した属性の値を取り出す。
存在しない属性ならば、#fを返す。


次に、指定したアイテムを使う手続きuse-item!を作ってみる。
!で終わっているのは、破壊的変更だから。アイテムは使うと無くなっちゃうからねー。

(define use-item!
  (lambda (action item)
    (and-let* (((has-item? item))
               ((item-property-get action item)))
      (begin
        (delete-item! item)
        #t))))

本を見ずに書いたらこんな感じになった。
この手続きが何を返すのかとか、規定されていなかったので仕方ないか。
本ではprintした後に、常に#tを返してるけど、なんか違和感。


ってか、それ以前に、has-item?(id:yagiey:20090307:1236410294)とdelete-item!(id:yagiey:20090307:1236410958)は使っちゃダメだよね。
だって*inventory*から消してしまうし。
ってことで、use-item!に合うようにそれぞれ書き換えてみた。

(define has-item?
  (lambda (item)
    (assoc item *item-database*)))

(define delete-1
  (traverse '()
             (lambda (x) (car (car x)))
             cdr
             (lambda (loop db) (cons (car db) (loop (cdr db))))))
  
(define delete-item!
  (lambda (item)
    (set! *item-database*
          (delete-1 item *item-database*))))

ってなると思うなぁ。
手続きtraverseはid:yagiey:20090309:1236597824を参照。
じゃ、use-item!を使ってみる。

gosh> (use-item! 'eat 'cookie)
#t
gosh> *item-database*
((potion (drink . #t) (throw . #t))
 (elixir (drink . #t) (throw . #t))
 (pancake (eat . #t) (throw . #t))
 (dragger (throw . #t)))

おぉ、クッキー喰った!