当你说这种方言“没有 NIL 变量”时,你在两个方面是对的。 nil 不仅不存在,而且似乎被视为可以用作变量的普通符号。它说“变量未定义”。
在nil具有特殊含义的Lisp方言中,nil通常不能用作变量。
nil 仅在“经典” Lisps(我的术语)中等同于 ()。我的意思是与原始 John MacCarthy Lisp 的祖先或模仿相关的 Lisp。 Emacs Lisp 和 Common Lisp 就是这样。经典的 Lisps 使用 nil 作为列表终止符:即 (cons 1 nil) 产生列表 (1)
从这个意义上说,Scheme 不是经典的 Lisp。没有nil。它使用() 作为空列表的打印符号,当您希望在表达式中使用该值时,它会被引用,就像非空列表文字一样:'()。在 Scheme 中,(cons 1 nil) 写作(cons 1 '())。布尔值 false 由标记为 #f 的对象表示。一个空列表是 true 不是 false,所以 (if '() 1 2) 产生 1,而不是像经典 Lisp 中的 2。 '() 和 #f 都不是符号。
方案也区分大小写。即使你在Scheme中有一个变量NIL,它也与nil无关。您可以将两者都用作变量名。
SICP 文本在其早期章节中引用了一个名为nil 的变量,该变量包含'() 的值,从而导致了对该主题的混淆。 Scheme中没有这样的变量;如果你想让这些例子起作用,你必须自己做。这是教科书的一个不幸方面。
如果你定义一个变量nil,它的值是对象'(),这样来自SICP的第2章代码就可以工作,它仍然不等同于在经典Lisp中的空列表,因为在在经典的 Lisp 中,nil 和 () 是符号的等价符号。符号nil 本身就是空列表,反之亦然。它不是仅包含列表的变量的名称。所以引用表达式'nil 也计算为空列表!而在方案 'nil 中,即使您已将其定义为保存空列表的变量,它也会计算为普通符号 nil。
关于第二个问题,“() 似乎有效,两者的含义相同吗?”。上面涵盖了“相同含义”方面:不,Scheme中的含义不同。就其工作而言,请考虑 R5RS 计划报告中的以下引用:
注意:在许多 Lisp 方言中,空组合 () 是合法的表达方式。在 Scheme 中,组合必须至少有一个子表达式,因此 () 不是语法上有效的表达式。 [4.1.3 过程调用]
因此,将() 作为产生空列表的有效表达式的这种松散处理似乎是 PC 方案的行为扩展,而不是标准方案。它正在接受一个在语法上不是有效的 Scheme 表达式的表达式。