Tho*_*mas 3 lisp scheme common-lisp expression-evaluation empty-list
我正在使用这个Lisp 编译器进行测试
有一件事情我不明白:如果一个空列表()评估自身:
(format t "~:a" ())
;; => ()
Run Code Online (Sandbox Code Playgroud)
为什么评估几个嵌套的空列表()不会评估为空列表?
(format t "~:a" (()))
;; => EVAL: undefined function NIL
;; why not () ?
(format t "~:a" ((())))
;; => EVAL: (NIL) is not a function name; try using a symbol instead
;; why not () ?
Run Code Online (Sandbox Code Playgroud)
从我的角度来看,()和NIL是相同的,所以内部空列表应该首先评估自身,然后外部列表应该“调用”新的内部评估空列表
我的头脑,我认为在进行计算时应该发生这样的情况:(粗体+斜体=当前评估的内容)
(()) => ( () ) => ( () ) => ()
似乎计划也不允许嵌套空列表调用
感谢您的阅读
在 Common Lisp 及其祖先中,空列表()是通过特殊分配进行自我评估的:它是唯一具有此属性的列表。它也是唯一一个也是符号的列表,在本例中是符号nil(实际上是符号NIL)。人们很容易认为,在实现的内部某个地方,只是说了相当于 的内容(defconstant nil ()),但它比这更神奇:
> (eq () 'nil)
t
> (symbolp ())
t
> (symbol-name ())
"NIL"
Run Code Online (Sandbox Code Playgroud)
这不仅仅是符号的价值nil,它本身就是符号nil。 ()CL真的很神奇。比在Scheme中更神奇,比如说:在Scheme中它仍然是神奇的,只是不那么神奇了。在Scheme中,()是唯一一个不是一对(缺点)的列表,但它也不是一个符号,并且它不是自我评估的。
所以,好吧,这解释了为什么要()对自身求值:它这样做是因为它很神奇。
所以现在考虑尝试评估这种形式:
(())
Run Code Online (Sandbox Code Playgroud)
好吧,首先这不是空列表:它是一个只有一个元素的列表,即空列表。从评价的角度来看它是一种复合形式。好吧,由于空列表(该列表的第一个元素)也是我们 nil可以将这个复合形式重写为
(nil)
Run Code Online (Sandbox Code Playgroud)
这是同一件事:(equal '(nil) '(()))是真的。
好的,现在评估者如何处理复合形式?它查看它们的第一个元素并决定要做什么(请参阅此处.
如果它是一个符号,那么该符号应命名为以下之一
并将进行相应处理。
如果它不是一个符号,它可能是一个列表开头(lambda ...),它被转换成一个匿名函数并被调用。
没有更多的病例了。
那么,哪个是(()),或者等效的(nil)?它是一种复合形式,它的第一个元素是符号nil。所以
nil指定一个特殊的操作员?不——(special-operator-p 'nil)是假的;nil命名宏吗?不——(macro-function 'nil)是假的;nil命名一个函数吗?不 -(fboundp 'nil)是假的。因此评估者无法处理此表单:它不合法。
请注意,在Scheme中,同样的事情也是不合法的,但原因略有不同:对于Scheme,空列表不是自我评估的,因此评估器看到(())并说(这次忽略宏)这是一个过程调用,其中过程将是评估 的结果(),但这是一个错误。如果我说(define nil '())then(nil)仍然是一个错误:它将评估nil并获取(),但()不是一个过程。
CL 的一个令人惊讶的事情是它(())可以被赋予(本地)含义。令人惊讶的是,这符合 CL:
(flet ((() () ()))
(()))
Run Code Online (Sandbox Code Playgroud)
CL它是一致的,因为如果符号没有全局函数定义,则允许在本地为符号建立函数定义:
如果包的外部符号
COMMON-LISP未定义为标准化函数、宏或特殊运算符,则允许将其词法绑定为函数(例如, withflet),以声明ftype该绑定的 ,并且(在提供这样做的能力)来追踪该绑定。——CLHS
然后是没有全局函数定义的()符号。nil