宏中的消息打印两次

Message in macro printed twice

我编写了一个函数,它可以接受任何类型、任意数量的参数,因此它可以打印参数的名称和值。该功能按预期工作。但我不喜欢函数调用要求我传递像这样 (my-message 'emacs-version 'emacs-copyright) 的引用值。我想简化为 (my-message emacs-version emacs-copyright)。所以我用宏来重写函数。

(defmacro my-message (&rest args)
  (if args
      (progn
        (message "This is the start of debug message.\n")
        (dolist (arg args)
          (cond
           ((stringp arg)
            (message arg))
           ((numberp arg)
            (message (number-to-string arg)))
           ((boundp arg)
            (pp arg)
            (message "")
            (pp (symbol-value arg)))
           ((not (boundp arg))
            (pp arg)
            (message "Undefined")))
          (message "\n"))
        (message "This is the end of debug message."))
    (message "This is a debug message ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")))

但是,某些消息被打印了两次。

(my-message emacs-version emacs-copyright 12345 "HelloWorld" foobar)

This is the start of debug message.

emacs-version
"24.5.1"
 [2 times]
emacs-copyright
"Copyright (C) 2015 Free Software Foundation, Inc."
 [2 times]
12345
 [2 times]
HelloWorld
 [2 times]
foobar
Undefined
 [2 times]
This is the end of debug message.

有什么问题?

您使用宏的原因不对。

宏不仅仅是避免代码中出现额外字符的噱头。

宏对代码进行操作。 IOW,您编写的代码在编译时(或宏扩展时,如果未编译)执行,然后使用结果而不是宏形式。

因此,您的宏的符号(更一般地说,sexp)部分应该如下所示

`(message "symbol: %s, value: %s" ',arg ,arg)

如果您不理解以上内容,请继续阅读 backquote

但是,让我重复一遍:宏是 "advanced material",在您熟悉 Lisp 之前,您可能更愿意避免使用它们。

我觉得留言 [2 times] 在你的输出中指的是一个额外的换行符。

可以通过评估重现此行为

(progn
  (message "HelloWorld")
  (message "\n"))

在*scratch*。 *messages* 中的输出是

HelloWorld
[2 times]
"
"

我想知道这种行为是否是故意的。

也许我确实误解了你的问题,因为我的回答与宏无关。