Function 宏定义和函数定义之间的区别

Function 宏定义和函数定义之间的区别,function,macros,lisp,common-lisp,Function,Macros,Lisp,Common Lisp,我正试图学习Lisp,但我被这个例子困住了(你可以在Paul Graham的“ANSI Common Lisp”中找到它,第170页): (定义宏输入(obj和rest选项) (let((insym(gensym))) `(let(,insym,obj)) (或,@(mapcar#’(lambda(c)`(eql,insym,c)) 选择(())())) 格雷厄姆接着说: 如果第一个参数是eql,则中的第二个宏[…]将返回true。我们可以将表达式写成: 否则,我们将不得不按照 为什么我应该写

我正试图学习Lisp,但我被这个例子困住了(你可以在Paul Graham的“ANSI Common Lisp”中找到它,第170页):

(定义宏输入(obj和rest选项)
(let((insym(gensym)))
`(let(,insym,obj))
(或,@(mapcar#’(lambda(c)`(eql,insym,c))
选择(())()))
格雷厄姆接着说:

如果第一个参数是
eql
,则中的第二个宏[…]
将返回
true
。我们可以将表达式写成:

否则,我们将不得不按照

为什么我应该写一个宏,而我写的以下函数的行为似乎与之相同

(defun in-func (obj &rest choices)
    (dolist (x choices)
        (if (eql obj x)
            (return t))))

我不明白我是否遗漏了什么,或者在这种情况下,func
中的
等同于
中的

使用宏vs函数的区别在于是否总是计算所有选项。

宏中展开的
按顺序计算选项。如果到达第一个参数的eql选项,它将返回一个真值,而不再求值
表格


>在FUNC < /代码>函数中的<代码>将评估函数调用时的所有选择。

< P>这两个答案是正确的,但为了使事情更具体,请考虑这种相互作用:

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

您缺少的一点是,
dolist
也是一个宏,尽管它更为复杂。geekosaur:是的,
dolist
是一个宏,但一般来说,如果您可以对函数执行同样的操作,那么避免编写新宏是一个很好的方法。宏可能会使未来的读者更难编写代码,因为它们不遵循通常的求值规则。(当然,在这种情况下,
中的
被定义为宏正是因为这样。)@Eli yep,这正是我关心的问题。这意味着如果我的函数是引用透明的,宏和函数之间就没有区别了?
(defun in-func (obj &rest choices)
    (dolist (x choices)
        (if (eql obj x)
            (return t))))
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