Lisp 中值的内存表示

Memory representation of values in Lisp

我读到,在原始的 lisp 中,CONS 在内存中以 36 位表示,前 18 位用于 CAR(15 位是地址,3 位表示它是 ATOM 的地址还是另一个 CONS),后 18 位位用于 CDR(15 位...)。我的问题是,如果 ATOM 需要多于一个字节,例如字符串,那么它的表示形式是什么?

"Lisp" 是一个 家族 的语言,而不是单一的语言。家族中的许多语言(例如 Common Lisp)不指定内部表示,而是指定结构和函数必须保留的契约。在 cons 的情况下,大致是等式:

(car (cons x y)) == x
(cdr (cons x y)) == y

以及每次调用时 cons returns 一个新对象的要求。在某些 Lisp 中,cons 单元是不可变的,因此不存在返回新对象的要求。

当然,实际上是有实现的,他们确实需要存储东西,问他们是怎么做到的也不是没有道理的。通常,最好将 cons 单元格视为一个大到足以容纳两个指针的结构,并且可能包含一些保存其类型的信息(以便它可以被识别为 cons 单元格)。但是,实现使用的指针可能会被标记,因此如果例如前三位是一些特殊值,则 "pointer" 可以被识别为某些原始值的编码。

这里的重要部分是你通常不需要知道机器上的底层表示,而且在你知道的情况下(例如,如果你正在编写代码来与另一种语言交互(例如, C)),那么您正在寻找的答案将特定于每个实现。

第一个 LISP 没有字符串。它只有符号和缺点。 John McCarthy's paper 中略微描述了如何存储符号字母。这些字母被编码为 6 位,每个地址为 5 个字母留出空间。一个列表(称为关联列表)将这些放在一起,这样您就可以拥有超过 5 个字母符号。

用户永远不会接触到这些结构,所以你怎么做并不重要。我在 BrainF*ck 中制作了自己的 McCarthy Lisp,Zozotez,并将我的符号名称编码为 cons,其中 car 始终是一个 ascii 值,而 cdr 要么是一个新值cons 用字母或 NIL

PS:现代 Lisps 将字符作为原始类型,类似于符号。字符串是字符序列。 Common Lisp 使用具有特殊类型的一维数组(=向量)来将字符串与其他数组区分开来,并要求它们具有字符元素。与其他向量和列表一样,您不能只比较值,而是使用字符串谓词或 equalequalp 来比较序列的各个部分。

最常见的是,引用符号的 cons 单元仅包含指向描述它的某个结构的指针。所以EQ可以实现为指针比较。三个额外的位用于保留一些类型信息,因此即使是 FIXNUMS 也可以这样编码和比较。