マクロを使用してクラス インスタンスを作成したいと考えています。
つまり、次のような式を作成したいということです。
(make-instance 'message :id id :mid mid)
このようにクラスを定義します。
(defclass message ()
((id
:initarg :id
:initform 0
:accessor id)
(mid
:initarg :mid
:initform 0
:accessor mid)))
(defmethod print-object ((obj message) stream)
(print-unreadable-object (obj stream :type t)
(with-slots (id mid) obj
(format stream "~A ~A " id mid))))
そしてマクロはこんな感じ。
(defun slotlist (alist)
(mapcan
#'(lambda (x)
(let* ((s (closer-mop:slot-definition-name x))
(k (intern (symbol-name s) :keyword))
(v (assoc k alist)))
(if v (list k (cdr v)))))
(closer-mop:class-direct-slots (find-class 'message))))
(defmacro create-message (alist)
(let ((a (gensym)))
`(let ((,a (slotlist ,alist)))
(make-instance 'message ,@a))))
そして次のようなjson-obj:
(setq json-obj '((:id . 1) (:mid . 2)))
マクロ create-message を適用すると
(create-message json-obj)
次のように展開します。
(LET ((#:G1111 (SLOTLIST JSON-ALIT)))
(MAKE-INSTANCE 'MESSAGE . #:G1111))
ただし、インスタンスの値が # であることを示しているため、インスタンスは正しく初期化されません。
map 関数の文字列をつなぎ合わせて apply 関数を使用する必要がありますか?