正如标题所说:为什么and
是宏而不是函数?
我试图申请并列出错误,经过一些搜索,我发现我应该做一些像(every #'identify list)
这样的事情。
但现在我想知道为什么and
是一个宏,我找不到任何好的解释。
答案 0 :(得分:4)
想象一下这个功能:
(defun my-every (predicate list)
(or (null list)
(and (funcall predicate (car list))
(my-every predicate (cdr list)))))
如果and
或or
是函数,则此函数将始终为无限循环。这同时使用了or
和and
短路的事实。例如,如果list
为nil
,则整个事件为t
,并且不会进行进一步处理。如果(funcall predicate (car list))
为nil
,则结果为and
短路错误。
事实上,or
和and
都可以使用if
来实现,因此可以像这样编写它:
(defun my-every (predicate list)
(if (null list)
T
(if (funcall predicate (car list))
(my-every predicate (cdr list))
NIL)))
答案 1 :(得分:2)
逻辑运算符和控制结构
and
根据定义并设计了控制结构和逻辑运算符。
and
和or
等逻辑运算符也是有用的控制结构。因此它们不能是一个函数,因为在调用运算符之前会对所有参数进行求值。人们需要将它们定义为内置运算符或作为函数。 Common Lisp by design具有最少数量的内置运算符,而and
/ or
功能可以由宏提供,它扩展为其他结构,如...因此选择那些是宏。
CLtL2
以这种方式描述:
换句话说,
and
特殊形式会对布尔评估进行短路,例如Ada中的and then
运算符,以及某些类似Pascal的语言中的cand
( for conditional和); Lisp和特殊形式不同于Pascal或Adaand
运算符,它总是计算两个参数。
文字中的轻微错误:(and ...)
不是特殊形式,而是宏形式。