【发布时间】:2015-01-24 18:11:20
【问题描述】:
我读到在原始 lisp 中,CONS 在内存中以 36 位表示,前 18 位用于 CAR(15 位是地址,3 位告诉它是 ATOM 的地址还是另一个 CONS),后 18 位是对于 CDR(15 位 ...)。我的问题是,如果 ATOM 需要超过一个字节,例如字符串,它的表示形式是什么?
【问题讨论】:
标签: lisp
我读到在原始 lisp 中,CONS 在内存中以 36 位表示,前 18 位用于 CAR(15 位是地址,3 位告诉它是 ATOM 的地址还是另一个 CONS),后 18 位是对于 CDR(15 位 ...)。我的问题是,如果 ATOM 需要超过一个字节,例如字符串,它的表示形式是什么?
【问题讨论】:
标签: lisp
“Lisp”是一个家族语言,而不是单一语言。该家族中的许多语言(例如,Common Lisp)没有指定内部表示,而是指定结构和功能必须保留的合同。在cons的情况下,大致是等式:
(car (cons x y)) == x
(cdr (cons x y)) == y
以及要求 cons 每次调用时都返回一个新对象。在某些 Lisps 中,cons 单元格是不可变的,因此不存在返回新对象的要求。
当然,实际上是有实现的,而且它们确实必须存储东西,问他们如何做到这一点并不是没有道理的。一般来说,最好将 cons 单元格视为一个足够大的结构以容纳两个指针,并且可能包含一些保存其类型的信息(以便可以将其识别为 cons 单元格)。但是,实现使用的指针可能会被标记,因此如果例如前三位是一些特殊值,则“指针”可以被识别为一些原始值的编码。
这里的重要部分是您通常不需要知道机器上的底层表示,并且在您知道的情况下(例如,如果您正在编写代码以与另一种语言(例如,C )),那么您正在寻找的答案将针对每个实现。
【讨论】:
第一个 LISP 没有字符串。它只有符号和缺点。 John McCarthy's paper 中略微描述了符号字母的存储方式。字母编码为 6 位,每个地址为 5 位。一个列表(称为关联列表)将这些组合在一起,因此您可以拥有超过 5 个字母符号。
用户永远不会接触到这些结构,所以你如何去做并不重要。我在 BrainF*ck 中制作了自己的 McCarthy Lisp Zozotez,并将我的符号名称编码为 cons,其中 car 始终是 ascii 值,cdr 要么是带有字母的新缺点,要么是 NIL .
PS:现代 Lisps 将字符作为原始类型,类似于符号。字符串是一个字符序列。 Common Lisp 使用具有特殊类型的一维数组(=vectors)来区分字符串和其他数组,并要求它们具有字符元素。与其他向量和列表一样,您不能仅将其作为值进行比较,而是使用字符串谓词或 equal 和 equalp 来比较序列的各个部分。
【讨论】:
最常见的引用符号的 cons 单元格只包含一个指向描述它的结构的指针。所以 EQ 可以实现为指针比较。这三个附加位用于保存一些类型信息,因此即使是 FIXNUMS 也可以通过这种方式进行编码和比较。
【讨论】: