2016-03-02 56 views

回答

4

write函数的结果是它的参数。因此,(write "Tom")的结果是"Tom"(它写入输出流的事实是函数的副作用)。

宏返回一个表单进行评估,这通常意味着一个列表。

您的宏创建列表(1 2 3),然后写出它。 write在宏展开时间评估,而不是“运行时”。由于write将其参数作为其返回值返回,而write是最后一个调用的函数,所以宏函数的结果是write函数的结果,或者在此例中为(1 2 3)。然后

(1 2 3)进行评估,但如果您尝试顶层打字(1 2 3),它会看到1为形式的第一个参数,并试图评估,作为一个功能 - 它不是,它只是数字1

如果你想看到你的宏将扩大什么,你可以尝试:(macroexpand '(createlist 1 2 3))

你可以看到下面的结果:

[2]> (macroexpand '(createlist 1 2 3)) 
(1 2 3) 
(1 2 3) ; 
T 

你见T他首先(1 2 3),这是你的write的结果。然后您会看到第二个(1 2 3),这是宏扩展(上面讨论)的结果,其次是T,这是macroexpand函数的结果。

所以这就是发生了什么事。不清楚如何解决它,因为它不清楚你想要做什么。

也许这就是你越希望做什么:

(defmacro createlist (a b c) 
    `(list ,a ,b ,c)) 

[5]> (macroexpand `(createlist 1 2 3)) 
(LIST 1 2 3) ; 
T 
+0

WOW!这很快!它帮助了很多!自从我开始学习LISP以来,我不知道'write'函数。您提供的解决方案正是我所需要的。 – L3M0L

2

write返回您传递给它,因为它是第一个参数的对象。因此,您从宏返回lst。无论你从宏返回什么都被视为lisp代码。

当运行你的代码,你应该看到

(1 2 3) 
在标准输出

只是错误之前。这就是你给到write什么:的(list a b c)a结果被绑定到1

在Lisp代码列表的第一个元素是被调用的函数。显然,1,这是这个列表的第一个元素,不是一个函数。

为了调试这样的错误,使用macroexpand往往是有帮助的:

(defmacro createList (a b c) 
    (let ((lst (list a b c))) 
    (write lst))) 

(format t "~%Expanded ~a~%" (macroexpand-1 '(createList 1 2 3))) 

(Live)