为什么AND是一个普通的lisp宏

时间:2015-12-06 22:34:15

标签: lisp common-lisp

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

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

2 个答案:

答案 0 :(得分:4)

想象一下这个功能:

(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)))

答案 1 :(得分:2)

逻辑运算符和控制结构

and根据定义并设计了控制结构逻辑运算符

andor等逻辑运算符也是有用的控制结构。因此它们不能是一个函数,因为在调用运算符之前会对所有参数进行求值。人们需要将它们定义为内置运算符或作为函数。 Common Lisp by design具有最少数量的内置运算符,而and / or功能可以由宏提供,它扩展为其他结构,如...因此选择那些是宏。

CLtL2以这种方式描述:

  

换句话说,and特殊形式会对布尔评估进行短路,例如Ada中的and then运算符,以及某些类似Pascal的语言中的cand( for conditional和); Lisp和特殊形式不同于Pascal或Ada and运算符,它总是计算两个参数。

文字中的轻微错误:(and ...)不是特殊形式,而是宏形式。