2013-04-04 69 views
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'。

+2

我認爲代碼看起來不友好。我會建議擺脫APPEND,創建一個謂詞來檢測基於arglist的方法存在,併爲代碼編寫生成器函數。使用「功能抽象」。 – 2013-04-05 08:04:55

+0

謝謝!我會仔細研究一下,特別是因爲我更經常需要這個功能。 – 2013-04-05 12:08:02

回答

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))))) 

(這可以通過MACROEXPAND-1〜_AND〜給定的定義看)這意味着所示的呼叫被評估爲(大致)

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

這返回'T',如所見。