【问题标题】:Difference between a macro definition and function definition宏定义和函数定义的区别
【发布时间】:2011-08-18 03:08:24
【问题描述】:

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

(defmacro in (obj &rest choices)
    (let ((insym (gensym)))
        `(let ((,insym ,obj))
             (or ,@(mapcar #'(lambda (c) `(eql ,insym ,c))
                           choices)))))

格雷厄姆接着说:

第二个宏 [...] in 如果它的第一个参数是 eql 则返回 true 到任何其他参数。我们可以写成这样的表达式:

(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

【问题讨论】:

  • 您缺少的一件事是dolist 也是一个宏,尽管它更复杂。
  • geekosaur: 是的,dolist 是一个宏,但总的来说,如果您可以对函数执行相同的操作,那么避免编写 new 宏是有好处的。由于宏不遵循通常的评估规则,宏会使未来的读者更难编写代码。 (当然,在这种情况下,in 正是因此而被定义为宏。)
  • @Eli 是的,这正是我所关心的。

标签: function macros lisp common-lisp


【解决方案1】:

使用宏 vs 函数的区别在于是否总是对所有选择进行评估。

扩展的in 宏按顺序评估选项。如果它达到一个等于第一个参数的选择,它返回一个真值而不评估任何更多 表格。

相比之下,in-func 函数将在调用该函数时评估所有选择

【讨论】:

  • 也就是说,如果我的函数是引用透明的,那么宏和函数没有区别?
【解决方案2】:

另外两个答案是正确的,但为了使事情更具体,请考虑以下交互:

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

【讨论】:

    猜你喜欢
    • 2017-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多