2016-03-23 107 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