2016-03-23 110 views
0

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

什么问题?

回答

0

我觉得你的输出中的消息 [2 times] 引用了一个额外的换行符。

这种行为可以通过在*从头评估

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

*转载。 *消息*中的输出是

HelloWorld 
[2 times] 
" 
" 

我不知道这是否是此行为。

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

+0

这就是为什么生成[2倍]的真正原因。 – tom

2

您使用宏的原因不正确。

宏不只是一个噱头,以避免代码中的额外字符。

宏操作代码。 IOW,您编写的代码是在编译时(或宏展开时间,如果未编译的话)执行的,然后使用结果代替宏窗体。

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

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

backquote了解了,如果你不明白上面。

但是,让我再说一遍:宏是“高级材料”,您可能更愿意避开它们,直到您对Lisp更加舒适。

+0

我总是与宏混淆。我试着编写了代码,并给出了预期的结果。使用宏来产生结果的缺点是什么?虽然这不是直接回答这个问题,但它指出了另一个问题。所以你从我身上获得了+1奖金。 – tom