キーワード

ここのところ、( keyword . plist )という感じのリストをよく使っています。
例えば、(:material :specular '(1 0 0 1))みたいな感じです。
手で入力するのはこの程度にとどめたいのですが、デフォルト値とかが他に色々あるので、これを関数に渡して

(:MATERIAL :SPECULAR (0.2 0.2 0.2 1) :DIFFUSE (0.8 0.8 0.8 1) :AMBIENT
(0 0 0 1) :SHININESS 0 :COLOR-MATERIAL NIL)

と、こんな感じのものが取り出せるようにしています。

で、それが以下の関数なんですが、

(defun material (&KEY
		 (specular '(0.2 0.2 0.2 1))
		 (diffuse '(0.8 0.8 0.8 1))
		 (AMBIENT '(0 0 0 1))
		 (SHININESS 0)
		 (COLOR-MATERIAL nil))
  (list :material :specular specular :diffuse diffuse :ambient ambient
        :shininess shininess :color-material color-material))

こんなのをいくつも書くのは結構苦痛だったので、以下のようなマクロを書いて

(defmacro def-primitive-func (name lst)
  (let ((head (car lst))
	(arg (loop for i from 0 below (length (cdr lst))
		  when (= 1 (mod i 2))
		  collect (elt (cdr lst) i)))
	(body (mapcar #'(lambda (x) (if (consp x) (car x) x)) (cdr lst))))
  `(defun ,name (&key ,@arg)
     (list ,head ,@body))))

以下のように使うことにしました。

(def-primitive-func material
    (:material :specular (specular '(0.2 0.2 0.2 1))
	       :diffuse (diffuse '(0.8 0.8 0.8 1))
	       :ambient (ambient '(0 0 0 1))
	       :shininess (shininess 0)
	       :color-material (color-material nil)))

でも本当は以下のように書きたい。

(def-primitive-func material
    (:material (specular '(0.2 0.2 0.2 1))
	       (diffuse '(0.8 0.8 0.8 1))
	       (ambient '(0 0 0 1))
	       (shininess 0)
	       (color-material nil)))


文字列を経由すればできそうな気はするんだけど、
文字列を経由しない方法を探してみようかと。
なんだかツイートの延長っぽいかんじ。