为什么在公共lisp中是和宏

为什么在公共lisp中是和宏,lisp,common-lisp,Lisp,Common Lisp,正如标题所说:和为什么是宏而不是函数? 我试图应用并列出,但出现了一个错误,经过一些搜索后,我发现我应该做一些类似于(每个#'标识列表) 但是现在我想知道为什么和是一个宏,我找不到任何好的解释 想象一下这个功能: (defun my-every (predicate list) (or (null list) (and (funcall predicate (car list)) (my-every predicate (cdr list))))) 如

正如标题所说:
为什么是宏而不是函数? 我试图应用并列出,但出现了一个错误,经过一些搜索后,我发现我应该做一些类似于
(每个#'标识列表)

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

想象一下这个功能:

(defun my-every (predicate list)
  (or (null list)  
      (and (funcall predicate (car list))
           (my-every predicate (cdr list)))))
如果
是函数,则此函数将始终是一个无限循环。这既利用了
短路的事实。例如,如果
list
nil
,那么整个过程就是
t
,不做进一步的处理。如果
(funcall谓词(car list))
nil
,则这是由于
短路错误导致的结果

事实上,
都可以使用
if
来实现,因此可以这样编写:

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

逻辑运算符和控制结构

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

这样的逻辑运算符也是有用的控制结构。因此,它们不能是函数,因为所有参数都将在调用运算符之前进行求值。需要将它们定义为内置运算符或函数。按设计,Common Lisp具有最少数量的内置运算符,宏可以提供
/
功能,宏可以扩展为其他结构,如。。。因此,选择了这些宏

CLtL2
是这样描述的:

换句话说,
特殊形式进行短路布尔求值,就像Ada中的
操作符,以及在一些类似Pascal的语言中被称为
cand
(用于条件和);Lisp和特殊形式不同于Pascal或Ada
运算符,后者总是计算两个参数


文本中有一个小错误:
(and…
不是一个特殊的形式,而是一个宏形式。

因为如果它是一个函数,它总是会计算它的所有参数,这显然不是你想从
中得到的语义。当然,当你这样说时,很明显:-)。为什么不写一个答案,这样我就可以把它标记为已解决?有时候你想要的
的语义实际上只是布尔逻辑。我维护一种Lisp方言,
是一个宏,也是一个函数。因此,如果您想通过
映射两个布尔值列表,它可以正常工作。Common Lisp不允许
同时绑定为宏/运算符和函数。必须选择
是函数还是宏。
的评估控制方面在很多时候都是必不可少的,因此,由于函数是严格按值调用的,所以它是宏。