0

私は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-speci-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-speci-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、その必要がなければ、もっと幸せです。

4

1 に答える 1

0

スロットの代わりにexit-conditionson で指定されたジェネリック関数を定義してみませんか?i-spec

于 2012-11-21T16:04:19.987 に答える