2015-04-29 129 views
1

對不起,我試過幾次,我不能建立簡單的defmacro - 任何人可以幫助我與:的elisp:與拉姆達defmacro

所以,我想定義的宏將擴展爲:

(define-key keymap "*" (lambda() 
          (interactive) 
          (some-func "*"))) 

我想是這樣的:

(defmacro wrap-and-define-key (keymap key func) 
    `(define-key ,keymap ,key (lambda() (interactive) (,func ,key)))) 

而且它的工作原理:

(wrap-and-define-key keymap key func) 

但不與

(wrap-and-define-key keymap key 'func) 

工作如何改變defmacro語句,以最後一種形式的工作?謝謝!

+0

爲什麼它需要是宏?只需定義一個普通的函數。 – Barmar

+0

@barmar是啊,它似乎是更簡單和更有用的解決方案。順便說一句,我只是想在這裏瞭解一些關於defmacro的信息。謝謝! – Rustem

回答

2

你並不需要爲這個宏。

(defun wrap-and-define-key (keymap key func) 
    (define-key keymap key (lambda() (interactive) (funcall func key)))) 

(不要引用拉姆達形式,避免eval

不知道爲什麼你要這樣,但無論如何,這應該做你問什麼。

+2

儘管我同意,但我認爲指出您的代碼只能在詞法綁定模式下工作很重要。即你需要' - * - 詞法綁定:t - * - '在包含這段代碼的文件的第一行。 – Stefan

+0

@Stefan感謝您的評論! – Rustem

0

好了,找到工作,但不知道 - 那就是優雅的解決方案:

(defmacro wrap-and-define-key (keymap key func) 
    `(define-key ,keymap ,key '(lambda() (interactive) (eval (list ,func ,key))))) 
2

您的宏不適用於第二個示例的原因是'func作爲帶引號的參數進行傳遞,因爲對宏的參數不會自動計算。因此,宏中的lambda擴展爲:

(lambda() (interactive) ('func key)) 

但是,當以這種方式調用函數名稱時,不能引用函數名稱。只有lambda或未加引號的符號可以作爲函數調用表達式中的第一項出現。如果將宏更改爲:

(defmacro wrap-and-define-key (keymap key func) 
    `(define-key ,keymap ,key (lambda() (interactive) (funcall ,func ,key)))) 

它會工作。當lambda被調用時,'func被評估爲普通的func符號並傳遞給funcall。 funcall然後在函數名稱空間中查找符號(Elisp是Lisp-2)並調用它。

正如另一個答案中所建議的,您可以使用函數來完成此操作。無論是否啓用詞彙模式,此功能都將起作用:

(defun wrap-and-define-key (keymap key func) 
    (define-key keymap key `(lambda() (interactive) (funcall ',func ,key))))