我正在浏览this Scheme tutorial,在3 (Making Lists)部分,该人说you should write '() to represent an empty list
。但是对于我写过的每一个测试,它似乎与仅使用()
具有相同的效果。
另外,据我所知,引用意味着解释器不会评估表达式,但似乎解释器知道'
符号之后的内容,因为这样做(cons 1 '())
会产生{{ 1}},在执行此操作(1)
时会产生(cons 1 'abc)
,因此它知道(1 . abc)
是一个空列表但'()
不是。{/ p>
答案 0 :(得分:5)
某些Scheme实现允许将()
作为'()
的同义词,但只有引用的表单才是标准格式。
至于你的第二个问题:考虑
(define abc '(1 2 3))
(define def '(1 2 3))
(cons 0 'abc)
(cons 0 'def)
(cons 0 abc)
(cons 0 def)
在前两个表达式中,abc
和def
未被评估,因此它们保留符号。在后两者中,它们被评估为它们所代表的对象,它们都等于列表(1 2 3)
。
答案 1 :(得分:1)
TL; DR:为了确保您的应用程序按照设计运行,您应该引用空列表,因为它不确定它是否会起作用。请看下面的长答案。
至于Scheme如何对引用值起作用,引用'(+ 3 4 5)使表达式成为一个不被评估的常量。这就像制作一个包含代码的字符串,比如“if(a == 0)return 4;”在Java或C中。区别在于引用的表达式是结构化数据而不是字节序列。
(cons 1 'abc)
和(cons 1 '())
也是如此。缺点有两个值的占位符,这两个表达式以完全相同的方式设置两个值。只有display
(和repl
)知道以()
结尾的列表应该以不同的方式显示,而不是(1 . ())
,就像它实际存储一样。
关于需要引用空列表的长答案
这一切都归结为您正在使用的标准。今天的大多数实现都是R5RS
,并且它需要引用空列表,因为空列表不是表达式。实现可能仍然允许它,因为它不会干扰正确的Scheme应用程序。下面是R5RS report:
注意:在许多Lisp方言中,空组合()是一个 合法的表达。在Scheme中,组合必须至少有一个 subexpression,so()不是语法上有效的表达式。
这实际上发生在R3RS (under Procedure calls),所以它已经存在了一段时间。然而,当looking for it in R6RS似乎已从该部分消失时,我认为他们已将其还原,以便自我评估。但是,我无法在language changes part中找到它。
查看R7RS draft(注意:PDF)时,R5RS的部分又回来了,所以我猜这是R6RS报告中的一个错误。这可能是racket
(可能还有其他实现者)允许()
作为R6RS中的表达式的原因,以确保它即使在报告含糊不清时也能正常工作。