Let's write β

プログラミング中にできたことか、思ったこととか

Lispでdefmodel

Railsのmodelの定義が非常にうらやましかったので、ちょっとやってみました。

(defmacro defmodel (mname parent slots &rest options)
  (let ((indexed-slots-names (loop for slot in slots
				when (getf (cdr slot) :index)
				collect (car slot))))
    `(progn
       (elephant:defpclass ,mname ,parent
	   ,slots
	 ,@options)
       ,@(loop for sname in indexed-slots-names
	      collect
	      `(defun ,(symb (string-upcase  (mkstr "find-" mname "-by-" sname))) (val)
		 (elephant:get-instances-by-value ',mname ',sname val))))))

これで、自動的に:index tが指定されているスロットについてfind--by-がそれぞれに定義されます。

(macroexpand-1 '(defmodel person ()
	       ((first-name :initform "" :accessor first-name :initarg :fname :index nil)
		(last-name  :initform "" :accessor last-name  :initarg :lname))))
=>
(PROGN
 (ELEPHANT:DEFPCLASS PERSON NIL
                     ((FIRST-NAME :INITFORM "" :ACCESSOR FIRST-NAME :INITARG
                                  :FNAME :INDEX T)
                      (LAST-NAME :INITFORM "" :ACCESSOR LAST-NAME :INITARG
                                 :LNAME)))
 (DEFUN FIND-PERSON-BY-FIRST-NAME (VAL)
   (ELEPHANT:GET-INSTANCES-BY-VALUE 'PERSON 'FIRST-NAME VAL)))