您可能希望阅读理查德·加布里埃尔(Richard Gabriel)的文章,其中总结了Lisp1与Lisp2之争中Lisp社区正在讨论的问题。在前几个部分中,这篇文章有点过于深奥和缓慢,但是一旦您浏览到第5节,它就变得更容易理解了。基本上,Lisp1具有将符号映射到值的单一环境,并且这些值可以是“常规”值或函数。Lisp2具有(至少)两个命名空间(符号有一个函数值的插槽和一个普通值的插槽)。因此,在Lisp2中,您可以同时拥有一个名为foo的函数和一个名为foo的值,而在Lisp1中,名称foo只能引用单个值(函数或其他类型)。两种方法之间存在多个权衡和不同之处,请阅读该文章以获取详细信息。克里斯蒂安·奎内克(Christian Queinnec)的书籍《小片语的Lisp》也穿插着讨论这些差异的内容。
根据维基百科:是否为函数单独设置命名空间是Lisp社区争议的焦点。这通常被称为Lisp-1与Lisp-2之争。Lisp-1指Scheme的模型,而Lisp-2指Common Lisp的模型。基本上是关于变量和函数是否可以在没有冲突的情况下具有相同的名称。Clojure是Lisp-1,这意味着它不允许同时将相同名称用于函数和变量。
在Lisp-1中,一个符号只能有一个值。在Lisp-2中,一个符号可以有两个值,即当符号被解释为函数时的值和当符号被解释为值时的值。在Lisp-1的实现中,包含与符号关联的值的结构只有一个指向数据和类型的插槽。而在Lisp-2中,有两个指针,一个指向函数值,另一个指向变量值。在Common Lisp中,一个Lisp-2,你可以调用(symbol-function 'a)和(symbol-value 'a)来分别获取函数和值。如果'a被定义为add函数,并且(setq a 3),那么(a a a 1)将返回7。在Lisp-1中,你不能这样做,因为a只能是一种东西,而上下文不会改变其含义。在Common Lisp中,#'是symbol-function的缩写。 (setf (symbol-function 'a) #'+)将a设置为求和函数。如果你愿意,你可以创建一个函数a,它将a设置为最后一次调用a返回的值,也许如果计算a的代价很高的话。在Lisp-2中,如果你将一个函数赋值给一个符号,那么要调用该函数,你需要使用funcall运算符。
funcall
和function
操作符。在Lisp-1中,这些操作符会消失。 - Kaz