Common Lisp:如何在 SBCL 中引用括号

Common Lisp: How to quote parenthese in SBCL

在 Common Lisp 中,特殊运算符 quote 使任何后跟未评估的内容,如

(quote a) -> a
(quote {}) -> {}

但是为什么表格(quote())给我nil?我正在使用 SBCL 1.2.6,这是我在 REPL 中得到的:

CL-USER> (quote ())
NIL

有关此问题的更多信息:这是 PCL 第 24 章

中的一些代码
(defun as-keyword (sym)
  (intern (string sym) :keyword))

(defun slot->defclass-slot (spec)
  (let ((name (first spec)))
    `(,name :initarg ,(as-keyword name) :accessor ,name)))

(defmacro define-binary-class (name slots)
  `(defclass ,name ()
     ,(mapcar #'slot->defclass-slot slots)))

当宏展开为以下代码时:

(define-binary-class id3-tag
    ((major-version)))

(DEFCLASS ID3-TAG NIL
      ((MAJOR-VERSION :INITARG :MAJOR-VERSION :ACCESSOR MAJOR-VERSION)))

这是 NIL 而不是 () 在 class 名称之后 ID3-TAG.

nil() 是表达同一概念(空列表)的两种方式。

传统上,nil用于强调布尔值"false"而不是空列表,而()则相反。

通用 LISP HyperSpec says:

() ['nil], n. an alternative notation for writing the symbol nil, used to emphasize the use of nil as an empty list.

您的观察是由于一个对象具有不止一种表示。在 Common Lisp 中,reader(读取代码和表达式)将文本解析为结构和数据。当它是数据时,编写器可以再次打印出来,但它不会确切地知道最初读入数据时数据是如何表示的。编写器将按照默认和设置以一种方式精确地打印一个对象,即使有多种表示形式对于那个对象。

如您所见nilNILnILNiL、...、'nil'NIL()'() 都被读取为同一个对象。我不确定标准是否确切规定了它的默认表示形式,所以我猜某些实现会选择 NILnil 甚至 ().

之一

使用 cons 表示取决于 cdr 是否为 cons/nil:

'(a . nil)        ; ==> (a)
'(a . (b . c))    ; ==> (a b . c)
'(a . (b . nil))  ; ==> (a b)

通过数字,reader 可以获得有关您正在使用哪个基数的提示。如果文本中没有使用基数,它将使用任何 *read-base* 是:

(let ((*read-base* 2)) ; read numbers as boolean
  (read-from-string "(10 #x10)")) ; ==> (2 16) 

#x 告诉 reader 将其余部分解释为十六进制值。现在,如果您的 print-base 为 4,则上述答案将可视化为 (2 100).

总而言之.. Common Lisp 中的单个值可能有多个很好的表示,并且所有这些都将产生完全相同的值。如何打印值将遵循实现、设置甚至生成它们的函数的参数。它接受什么作为值或它可以可视化值的不同方式都没有说明值实际上是如何在内部存储的。