宏中的消息打印两次

时间:2016-03-23 04:45:40

标签: macros elisp message

我编写了一个函数,可以接受任何类型,任意数量的参数,以便它可以打印参数的名称和值。该功能按预期工作。但是我不喜欢函数调用要求我传递像(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.

有什么问题?

2 个答案:

答案 0 :(得分:2)

您出于错误的原因使用宏。

宏不仅仅是避免代码中多余字符的噱头。

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

因此,宏的符号(以及更一般地说,性别)部分应该看起来像

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

如果您不理解上述内容,请阅读backquote

但是,让我再说一遍:宏是高级材料"你可能更愿意避免它们,直到你对Lisp更加熟悉。

答案 1 :(得分:0)

我认为这个消息 [2 times] 在你的输出中引用了一个额外的换行符。

此行为可以通过评估来复制

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

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

HelloWorld
[2 times]
"
"

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

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