2012-11-18 2 views
5

Я заметил тенденцию в моем коде повторения того же (with-current-buffer .... снова и снова, поэтому я решил определить макрос, основанный на этом определении макроса with-current-buffer - это то, что у меня есть до сих пор:Тело defmacro не выполняется

(defmacro with-assembla-buffer(asm-buffer-name heading-str &rest body) 
    "Create buffer with name of ASM-BUFFER-NAME, or uses it if exists,                          
    preps it with readonly/erase/heading - executes `body' - then puts                          
    readonly back on, goes to beginning of buffer, and switches to it." 
    (with-current-buffer (get-buffer-create asm-buffer-name) 
    (assembla-mode) 
    (toggle-read-only -1) 
    (erase-buffer) 
    (insert (format "-- %s --------------------" heading-str)) 
    (newline) 
    `(progn ,@body) 
    (toggle-read-only 1) 
    (goto-char (point-min)) 
    (switch-to-buffer (current-buffer)))) 

тело этого никогда не выполняется, однако, когда он перешел на defun вместо defmacro это работает отлично. Итак, в стороне от почему тело никогда не было выполнено, мой другой вопрос - делает ли это больше смысла в качестве макроса, чем defun?

+0

Для цитирования Emacs-23's 'Ch f switch-to-buffer':« ПРЕДУПРЕЖДЕНИЕ: Это не способ временно работать с другим буфером в программе Lisp! Вместо этого используйте 'set-buffer'. Это позволяет избежать messing с соответствием оконных буферов " – Stefan

ответ

4

Помните, что макрос генерирует код. Ваш макрос выглядит так, как будто нет. Проверьте макрорасширение примера вызова. Первым шагом отладки макроса является проверка макрокомандирования некоторого кода.

....

(with-current-buffer (get-buffer-create asm-buffer-name) 

Выше: почему это в качестве кода в макрос, а не как исходный код? Этот код будет выполнен, когда макрос будет расширен, он не будет отображаться в сгенерированном коде. Вероятно, вы захотите его запрограммировать.

(assembla-mode) 
    (toggle-read-only -1) 
    (erase-buffer) 
    (insert (format "-- %s --------------------" heading-str)) 
    (newline) 

    `(progn ,@body) 

Выше: это не будет делать то, что вы хотите. Вам нужно запрограммировать ВСЕ код, который вы хотите создать, а не только эту форму.

+0

Я сделал backquote все это, и это имеет смысл. Благодаря! –

+1

Дэн: Также обратите внимание, что для байт-скомпилированного elisp макросы расширяются во время компиляции, и поэтому код, который выполняется макросом, будет * не * выполняться во время выполнения при работе с байтовым скомпилированным кодом. (Этот критический нюанс легко пропустить, потому что для некомпилированного кода макрос будет расширяться динамически, а код * будет выполняться каждый раз.) – phils

Смежные вопросы