2010-02-20 35 views
5

有沒有一種方法可以像使用macrolet一樣進行詞法關閉?我想要做的就是讓下面的宏本地遞歸輔助函數調用每個組合的功能,而不是生成因爲它現在要求在REPL結果宏列表:通過小型詞彙進行詞彙封閉?

CL-USER> (combinations nil '(1 2 3) '(4 5 6)) 
((1 4) (1 5) (1 6) (2 4) (2 5) (2 6) (3 4) (3 5) (3 6)) 

我想是一個宏,它接受一個函數和任意數量的列表並生成嵌套循環,這些循環調用每個組合的函數。我是lisp的新手,這是我在'nif'克隆之外編寫的第一個宏,所以有任何建議。 (nreverse(list,item,@ vars))''替換爲'(func(nreverse(list,item)'); ,@ vars)))'但我得到錯誤,說func是一個未定義的變量或函數。

這是原來的功能:

(defmacro combinations (vars &rest lsts) 
    (with-gensyms (item) 
    `(loop for ,item in ,(car lsts) ,(if (null (cdr lsts)) 'collecting 'nconcing) 
     ,(if (null (cdr lsts)) 
      `(nreverse (list ,item ,@vars)) 
      `(combinations (,item ,@vars) ,@(cdr lsts)))))) 

這是我已經試過macrolet並獲得未定義功能「功能」的錯誤。

(defmacro for-all-combonations (func &rest lst) 
     (macrolet ((for-all (vars &rest lsts) 
        (with-gensyms (item) 
         `(loop for ,item in ,(car lsts) ,(if (null (cdr lsts)) 
                  'collecting 'nconcing) 
          ,(if (null (cdr lsts)) 
           `(func (nreverse (list ,item ,@vars))) 
           `(for-all (,item ,@vars) ,@(cdr lsts))))))) 
     (for-all nil lst))) 
+2

你能解釋一下爲什麼你想使用這個宏嗎?什麼應該(讓((a'((1 2 3)(4 5 6))))(組合無))? – 2010-02-20 04:23:43

+0

它應該返回'(((1 2 3))(((4 5 6))),它是每個組合的每個輸入列表中取一個元素的所有組合的列表。我正在用宏來做這件事,因爲這正是我現在正在探索的。我可以在沒有宏的情況下做到這一點,但我想試着寫一個比nif複雜的宏。這讓我有機會找出可以做什麼和不可以做什麼,我永遠不會想知道是否可以用這種方式來使用小應用程序。希望一旦我完成這個,我會理解更好的宏。 – asm 2010-02-20 18:42:00

+2

我不認爲這與宏有關。宏可以用來計算源代碼,而不是數據。如果你想計算數據,數據需要在宏擴展時間 - 通常不是。 – 2010-02-20 23:37:34

回答

5

宏不是Common Lisp中的第一類對象,所以你不可能真正具有與宏一樣的詞法閉包。你可以通過創建一個生成一個有效的Lisp程序列表的函數來獲得相似的效果,然後對其進行處理。

雖然這可能不是一個很好的解決方案。正如Rainer Joswig所說,宏是用來操縱源代碼的。當你想要一種不屬於該語言的新語法形式時使用它們。不要在可以用普通函數寫你想要的東西的地方使用它們。

+0

好吧,你說服了我。我想這是這次探索的結束。 – asm 2010-02-22 02:16:50

+0

@Andrew Myers - 對於一流宏的想法已經有了一些探索。最近我讀到的是Paul Graham考慮Arc的想法。我認爲他最終放棄了它,因爲它使得編譯器對於不確定的好處更加複雜。 – Zak 2010-03-08 06:01:38