【问题标题】:Body of defmacro not being executeddefmacro 的主体没有被执行
【发布时间】:2012-11-18 21:51:02
【问题描述】:

我注意到我的代码中有一种趋势是一遍又一遍地重复相同的(with-current-buffer ....,因此我决定根据with-current-buffer 的宏定义来定义一个宏——这就是我目前所拥有的:

(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 时确实可以正常工作。所以除了为什么从不执行 body,我的另一个问题是 - 作为宏比 defun 更有意义吗?

【问题讨论】:

  • 引用 Emacs-23 的 C-h f switch-to-buffer:“警告:这不是在 Lisp 程序中临时处理另一个缓冲区的方法!请改用 set-buffer。这样可以避免弄乱窗口缓冲区通信”

标签: emacs lisp elisp


【解决方案1】:

请记住,宏会生成代码。你的宏看起来不像。查看示例调用的宏扩展。调试宏的第一步是检查某些代码的宏扩展。

....

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

以上:这不会做你想要的。您需要反引号所有要生成的代码 - 不仅仅是这个表单。

【讨论】:

  • 我确实反引号了整件事,这更有意义。谢谢!
  • Dan:还要注意,对于字节编译的 elisp,宏会在编译时扩展,因此宏执行的代码将不会在运行时执行-运行字节编译代码的时间。 (这个关键的细微差别很容易被忽略,因为对于未编译的代码,宏将动态扩展,并且每次都会执行代码。)
猜你喜欢
  • 1970-01-01
  • 2014-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-10
  • 2012-05-12
相关资源
最近更新 更多