3

次のマクロを定義しました。

(defmacro ~lazy (expression)
  `(lambda ()
     ,@expression))

(defgeneric force~ (value)
  (:method (value)
    value)
  (:method ((value function))
    (funcall value)))

(defmacro ~~ (expression)
  `(~lazy (force~ ,expression)))

[...] 次のマクロは、いくつかの標準メソッドが定義された名前「NAME」の汎用関数を定義します。これは「REDUCE」のように機能し、途中ですべての遅延値を強制する必要がありますが、一度でも遅延値と非遅延値に遭遇した場合は遅延値を返します (「~」で始まり、終了するマクロによって示されます)。

(defmacro ~lazy-reduce~ (name reduce-fun (arg-var args-var)
                         &body methods)
  (let ((first (gensym "first")))
    `(defgeneric ,name (,arg-var ,args-var)
       ,@(append
          (if (not (member `(,arg-var (,args-var cons))
                           methods
                           :key #'car
                           :test #'equal))
              `((:method (,arg-var (,args-var cons))
                  (let ((,first (first ,args-var)))
                    (if (functionp ,first)
                        (~~ (,reduce-fun (force~ ,first)
                                         (force~
                                          (,name ,arg-var
                                                 (rest ,args-var)))))
                        (,name (,reduce-fun ,arg-var ,first)
                               (rest ,args-var)))))))
          (if (not (member `((,arg-var function)
                             ,args-var)
                           methods
                           :key #'car
                           :test #'equal))
              `((:method ((,arg-var function)
                          ,args-var)
                  (~~ (,name (force~ ,arg-var)
                             ,args-var))))))
       ,@(mapcar (lambda (method)
                   (cons :method method))
                 methods))))

~_AND~ を次のように定義します。

(~lazy-reduce~ ~_and~ and (val vals)
   (((val null)
     vals)
    nil)
   ((val (vals null))
    val))

通話中

(~_and~ t (list 2))

正常に動作し、期待どおり「2」を返しますが、

(force~ ~_and~ t (list (~ 2)))

'T' だけを返します。

それがなぜなのかわかりませんが、「〜FIND-IF」を簡潔に定義することができません。

4

1 に答える 1

0

エラーが見つかりました: ~_AND~ の最初のメソッドは次のようになります:

(:method (val (vals cons))
 (let ((first (first vals)))
   (if (functionp first)
       (~~ (and (force~ first)
                (force~ (~_and~ val (rest vals)))))
       (~_and~ (and val first)
               (rest vals)))))

(これは、指定された ~_AND~ の定義で MACROEXPAND-1 によって確認できます)

これは、表示された呼び出しが (おおよそ) 次のように評価されたことを意味します。

(and (force~ (~ 2))
     T)

ご覧のとおり、これは 'T' を返します。

于 2013-04-04T13:47:59.630 に答える