他们为什么在Scheme中引用空列表?

时间:2013-10-19 16:03:55

标签: scheme

我正在浏览this Scheme tutorial,在3 (Making Lists)部分,该人说you should write '() to represent an empty list。但是对于我写过的每一个测试,它似乎与仅使用()具有相同的效果。

另外,据我所知,引用意味着解释器不会评估表达式,但似乎解释器知道'符号之后的内容,因为这样做(cons 1 '())会产生{{ 1}},在执行此操作(1)时会产生(cons 1 'abc),因此它知道(1 . abc)是一个空列表但'()不是。{/ p>

2 个答案:

答案 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)

在前两个表达式中,abcdef未被评估,因此它们保留符号。在后两者中,它们被评估为它们所代表的对象,它们都等于列表(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中的表达式的原因,以确保它即使在报告含糊不清时也能正常工作。