準クォート
リテラルデータに手続きを埋め込むにはちょっとした工夫が必要です。
ということだが、手続きに関わらず、評価済みの値を埋め込む場合一般的に言える話ですな。
gosh> (define foo '(hoge . (lambda (n) (+ n 1)))) foo gosh> foo (hoge lambda (n) (+ n 1))
gosh> (define bar `(fuga . ,(lambda (n) (+ n 1)))) bar gosh> bar (fuga . #<closure bar>)
バッククォートに続くS式の中で、カンマに続くS式を評価して、その評価結果をリテラルデータに埋め込む。
カンマがつかないS式は、クォートされたときと同じ。
上で言うと、fugaがそれ。評価されていない。
これを利用して、データベース*item-datebase*に手続きを保存しよう、と。
まさに、手続きをオブジェクトとして扱える言語だからできる芸当ですかね。
こんな感じ。
(define *item-database* `(postion (drink . ,(cut add-hp! <> 50)) (throw . ,(cut add-hp! <> -3))) `(elixir (drink . ,(cut add-hp! <> 50)) (throw . ,(cut add-hp! <> -3))) `(pancake (eat . ,(cut add-hp! <> 7)) (throw . ,(cut add-hp! <> -1))) `(dagger (throw . ,(lambda (_) #f))))
ってやっとけば、以下のようにしとけば、今までと同じやり方で、手続きを取得出来る、と。
ただ、今までは手続きではなく常に#tか#fを取得してたけど。
gosh> (item-property-get 'cookie 'eat) #<closure *item-database*> gosh> (item-property-get 'potion 'eat) #f
1個目は、評価結果が手続きであることを示す。しかし、なんで「*item-database*」という名前が表示されるのかは知らん。
2個目は、potionはeatできない、つまりeatに対する手続きが定義されていないから#fが返ったわけね。