私は2つのEIEIOクラスを持っています:
(defclass i-driver ()
(;; more slots
(exit-conditions
:initarg :exit-conditions
:initform nil
:type list
:documentation
"Conditions to test in the main (while ...) expression"))
:documentation "This class describes a single driver of `i-iterate' macro")
と:
(defclass i-spec ()
((exit-conditions
:type list
:reader i--get-exit-conditions
:documentation
"Conditions to test in the main (while ...) expression")
;; more slots
(drivers
:initform nil
:type list
:documentation
"This slot contains the list of all drivers used in this iteration macro"))
:documentation "This class contains a specification of the
expansion of the `i-iterate' macro")
私がしたいこと:
- オブジェクトのリストからフィールドを集約して、クラスを
exit-conditions
介してフィールドを公開します。私の最初のアイデアは、次のようにリーダーを定義できるというものでした。i-spec
i-driver
(defmethod i--get-exit-conditions ((spec i-spec))
(with-slots ((ds drivers)) spec
(let (result)
(while ds
(push (oref ds exit-conditions) result)
(setq ds (cdr ds)))
result)))
- に格納する必要があるだけなので、スロット
exit-conditions
をに割り当てたくありません。i-spec
i-driver
- また、スロットを読み取り専用にしたいです (対応するドライバーを変更することによってのみ変更できますが、スロット自体への書き込みでは変更できません)。
PS。著作権の主張の場合i
、名前は foriterate
であり、Wozniak が Apple の製品で使用したものではありません :)
編集:
これが私が今やっている方法です:
(defmethod i-aggregate-property ((spec i-spec) property &optional extractor)
(with-slots (drivers) spec
(let ((ds drivers)result)
(while ds
(if extractor
(setq result
(funcall extractor (slot-value (car ds) property) result))
(push (slot-value (car ds) property) result))
(setq ds (cdr ds))) result)))
そして、ここに醜い外観があります:
(defmacro i-iterate (&rest specs)
(let ((spec (i--parse-specs specs)))
(with-slots (body result) spec
(let* ((exit-conditions
(i-aggregate-property spec 'exit-conditions #'append))
(catch-conditions
(i-aggregate-property spec 'catch-conditions #'append))
(variables
(i-aggregate-property spec 'variables #'append))
(actions
(i-aggregate-property spec 'actions #'append))
(econds
(cond
((cdr exit-conditions)
(append '(and) (nreverse exit-conditions)))
(exit-conditions (car exit-conditions))
(t t)))
(vars (nreverse variables))
(body (append actions (nreverse body))))
(cond
((and catch-conditions vars)
(append catch-conditions
(list
`(let* (,@vars)
(while ,econds ,@body) result))))
(catch-conditions
(append catch-conditions
(list
`(while ,econds ,@body) result)))
(variables
`(let* (,@vars)
(while ,econds ,@body) ,result))
(t `(progn (while ,econds ,@body) ,result)))))))
この繰り返しの呼び出しを非表示にするマクロを追加して、 のようなものにすることもできますがwith-slots
、その必要がなければ、もっと幸せです。