为什么 AND 是 common lisp 中的一个宏

Why is AND a macro in common lisp

正如标题所说:为什么and是宏而不是函数? 我试图申请和列出并得到一个错误,经过一些搜索,我发现我应该做类似 (every #'identify list) 的事情。

但现在我想知道为什么and是一个宏,我找不到任何好的解释。

想象一下这个函数:

(defun my-every (predicate list)
  (or (null list)  
      (and (funcall predicate (car list))
           (my-every predicate (cdr list)))))

如果 andor 是函数,则此函数将始终是一个无限循环。这同时使用了 orand 短路的事实。例如,如果 listnil 那么整个事情就是 t 并且没有进一步的处理。如果 (funcall predicate (car list))nil 那么这是因为 and 短路错误的结果。

事实上,orand 都可以使用 if 来实现,所以也可以这样写:

(defun my-every (predicate list)
  (if (null list)
      T  
      (if (funcall predicate (car list))
          (my-every predicate (cdr list))
          NIL)))

逻辑运算符和控制结构

and 根据定义和设计都是 控制结构 逻辑运算符 .

andor 等逻辑运算符也是有用的控制结构。因此它们不能是函数,因为所有参数都将在调用运算符之前进行评估。需要将它们定义为 内置运算符 或函数。 Common Lisp 的设计具有最少数量的 内置运算符 并且 and/or 功能可以由宏提供,它扩展到其他结构,如...因此选择那些是宏。

CLtL2是这样描述的:

To put it another way, the and special form does short-circuit Boolean evaluation, like the and then operator in Ada and what in some Pascal-like languages is called cand (for conditional and); the Lisp and special form is unlike the Pascal or Ada and operator, which always evaluates both arguments.

文中略有错误:(and ...)不是特殊形式,而是宏形式