2016-07-23 64 views
0

如何有條件地刪除在lisp宏中創建的defun中的let-binding?在這裏,我想從結果函數中刪除第一個允許綁定的變量,但是我遇到了一個問題,我在綁定中有一個nil,導致錯誤。有條件地刪除lisp宏中的let-binding

例如,生成的函數使用letlet*,並應根據arg刪除第一個變量賦值。但我寫它的方式來自nil替換var1問題。我不知道如何擺脫零。

(cl-defmacro mac (cmd &optional arg) 
    (let ((fn (intern (concat "fn-" cmd)))) 
    `(defun ,fn() 
     (interactive) 
     (,(if arg 'let* 'let) 
     (cons 
     ,(when arg 
      '(var1 1)) 
     (var2 (if (bound-and-true-p var1) (+ var1 1) 1))) 
     (message "%s" var2))))) 

(mac "fun") ; Attempt to set constant: nil 
(mac "fun2" t) ; no problem 
;; (symbol-function 'fn-fun) 
;; (symbol-function 'fn-fun2) 
;; (fn-fun) 
;; (fn-fun2) 
+1

最簡單的解決方法是使用',@(當arg'((var1 1)))''時。這個'cons'應該是一個函數調用嗎?它被引用,所以現在你還定義了一個名爲'cons'的變量。對我來說看起來沒有必要。 – jkiiski

+0

'macroexpand'是你的朋友。用它來找出你的宏調用擴展到的內容。在這種情況下,它會告訴你相關部分擴展爲'(let(cons nil(var2 ...))...),它綁定一個名爲'cons'的變量並試圖綁定一個名爲'nil'。 – Drew

+0

您的問題本身不是關於Emacs Lisp的問題。這是一個關於Lisp宏的問題。我添加了標籤'lisp-macros',因爲在StackOverflow上,標籤'macros'並不意味着同樣的事情。 – Drew

回答

1

最簡單的解決方法可能是使用,@(when arg '((var1 1))),@用於將列表拼接到位置。由於WHEN返回NIL如果條件失敗,並且NIL與空列表相同,拼接有效地忽略它。當條件成功時返回((var1 1)),並且(var1 1)由拼接解開。