我正在尝试学习Lisp,但是我被这个例子困住了(你可以在“ANSI Common Lisp”上找到它,Paul Graham,第170页):
(defmacro in (obj &rest choices)
(let ((insym (gensym)))
`(let ((,insym ,obj))
(or ,@(mapcar #'(lambda (c) `(eql ,insym ,c))
choices)))))
然后格雷厄姆说:
如果第二个宏[...]
in
的第一个参数是true
,则返回eql
任何其他参数。我们可以写成的表达式:
(in (car expr) '+ '- '*)
否则我们必须写为
(let ((op (car expr)))
(or (eql op '+)
(eql op '-)
(eql op '*)))
为什么我应该在我写似乎以下的函数以同样的方式编写宏时写一个宏?
(defun in-func (obj &rest choices)
(dolist (x choices)
(if (eql obj x)
(return t))))
我不明白我是否遗漏了某些内容,或者在这种情况下,in-func
相当于in
。
答案 0 :(得分:7)
使用宏与功能的区别在于是否始终评估所有选项。
展开的in
宏会按顺序评估选项。如果它到达第一个参数的eql选项,它将返回一个真值而不再进行求值
形式。
相反,in-func
函数将在调用函数时评估所有选项。
答案 1 :(得分:3)
另外两个答案是正确的,但为了使事情更具体,请考虑这种互动:
CL-USER(1): (defmacro in ...)
IN
CL-USER(2): (defun in-func ...)
IN-FUNC
CL-USER(3): (defvar *count* 0)
*COUNT*
CL-USER(4): (defun next () (incf *count*))
NEXT
CL-USER(5): (in 2 1 2 3 (next))
T
CL-USER(6): *count*
0
CL-USER(7): (in-func 2 1 2 3 (next))
T
CL-USER(8): *count*
1