为什么在公共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不允许和同时绑定为宏/运算符和函数。必须选择和是函数还是宏。和
的评估控制方面在很多时候都是必不可少的,因此,由于函数是严格按值调用的,所以它是宏。