Lisp/Scheme:评估嵌套的空列表/缺点:(())

问题描述 投票:0回答:1

我正在使用这个 Lisp 编译器进行测试

有一件事我不明白: 如果一个空列表

()
评估自身 :

(format t "~:a" ())
;; => ()

为什么评估多个嵌套的空列表

()
不评估为空列表?

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

从我的角度来看,

()
NIL
是相同的,所以内部空列表应该首先评估自身,然后外部列表应该“调用”新的内部评估空列表

我的头脑,我认为在进行计算时应该发生这样的情况: (粗体+斜体=当前评估的内容)

(()) => (()) => (()) => ()

好像Scheme也不允许嵌套空列表调用

感谢您的阅读

scheme lisp common-lisp empty-list expression-evaluation
1个回答
1
投票

在 Common Lisp 及其祖先中,空列表

()
通过特殊分配进行自我评估:它是唯一具有此属性的列表。这也是唯一一个也是符号的列表,在本例中是符号
nil
(实际上是
NIL
)。人们很容易认为,在实现的内部某个地方,只是说了相当于
(defconstant nil ())
的东西,但它比这更神奇:

> (eq () 'nil)
t

> (symbolp ())
t

> (symbol-name ())
"NIL"

这不仅仅是符号

nil
的值,它就是符号
nil
()
在CL中真的很神奇。比在Scheme中更神奇,比如说:在Scheme中它仍然是神奇的,只是不那么神奇了。在Scheme中,
()
是唯一不是一对(缺点)的列表,但它也不是一个符号,也不是自评估的。

所以,好吧,这解释了为什么

()
会评估自身:它这样做是因为它很神奇。

所以现在考虑尝试评估这种形式:

(())

好吧,首先这不是空列表:它是一个只有一个元素的列表,这是空列表。从评价的角度来看,它是一个复合形式。好吧,由于空列表(该列表的第一个元素)是 also

nil
,我们可以将这个复合形式重写为

(nil)

这是同一件事

(equal '(nil) '(()))
是真的。

好的,现在评估者如何处理复合形式?它会查看第一个元素并决定要做什么(请参阅此处

  • 如果它是一个符号,那么该符号应命名为以下之一:

    • 特殊操作员
    • 或(可能是本地)函数
    • 或(可能是本地)宏

    将会进行相应处理。

  • 如果它不是一个符号,它可能是一个以

    (lambda ...)
    开头的列表,它被转换为匿名函数并被调用。

  • 没有更多案例了。

那么,哪个是

(())
,或者等效的
(nil)
?它是一种复合形式,它的第一个元素是符号
nil
。所以

  • nil
    是否命名了一个特殊的运算符?否 --
    (special-operator-p 'nil)
    是假的;
  • nil
    命名宏吗?否 --
    (macro-function 'nil)
    是假的;
  • nil
    命名一个函数吗?不 -
    (fboundp 'nil)
    是假的。

因此评估者无法处理此表格:它不合法。


请注意,在Scheme中,同样的事情也是不合法的,但原因略有不同:对于Scheme,空列表不是自我评估的,因此评估者看到

(())
并说(这次忽略宏)这是过程调用,其中过程将是评估
()
的结果,但这是一个错误。如果我说
(define nil '())
那么
(nil)
仍然是一个错误:它将评估
nil
并得到
()
,但
()
不是一个过程。

© www.soinside.com 2019 - 2024. All rights reserved.