まだ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)))
おぉ、クッキー喰った!