You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Common Lisp中使用'#(...)和#(...)创建向量有实际差异吗

Common Lisp 字面量向量创建方式的差异与开发影响

在 SBCL 环境下,我们可以用两种写法创建字面量向量,返回值看起来完全一致:

CL-USER> '#(a b c)
#(A B C)

CL-USER> #(a b c)
#(A B C)

对两个返回值执行type-of和describe查询,结果也没有区别:

CL-USER> (type-of #(a b c))
(SIMPLE-VECTOR 3)
CL-USER> (type-of '#(a b c))
(SIMPLE-VECTOR 3)
CL-USER> (describe #(a b c))
#(A B C)
  [simple-vector]

Element-type: T
Length: 3
; No value
CL-USER> (describe '#(a b c))
#(A B C)
  [simple-vector]

Element-type: T
Length: 3
; No value

用按值比较的equalp判断返回为真:

CL-USER> (equalp '#(a b c) #(a b c))
T

但用equal判断则返回假,甚至两个完全相同的'#(a b c)写法的返回值用equal比较也为假:

CL-USER> (equal '#(a b c) #(a b c))
NIL
CL-USER> (equal '#(a b c) '#(a b c))
NIL

核心原因与开发影响

本质差异澄清

首先需要明确:#(...)是Common Lisp的读取器宏,本身返回的就是字面量常量向量,在前面加单引号'只是额外加了一次quote操作,对最终结果没有任何影响,两种写法得到的对象完全等价。
equal返回NIL的原因是:Common Lisp标准规定,equal对于列表以外的序列类型(包括向量),仅判断两个对象是否是同一个内存对象(即eq判断),而SBCL实现不会对内容相同的字面量向量做常量合并,每次读取到#(...)字面量都会生成新的内存对象,所以哪怕写法完全一致,得到的也是不同的对象,equal自然返回NIL。

实际开发中的注意事项

  • 禁止修改字面量向量:无论加不加单引号,#(...)写法得到的都是常量向量,Common Lisp标准明确规定修改字面量常量属于未定义行为,SBCL中直接修改字面量向量的元素会触发运行时报错。如果需要可修改的向量,不要使用字面量写法,应该用vector函数或者make-array函数动态创建,例如(vector 'a 'b 'c)得到的就是可修改的向量。
  • 选对相等性判断函数:如果需要判断两个向量的内容是否相同,统一使用equalp,不要用equal,equalp会对所有序列类型执行逐元素的递归值比较,符合绝大多数业务场景的相等判断需求。
  • 不要依赖字面量的对象同一性:无论写多少次相同内容的#(...)字面量,都不要假设它们会指向同一个内存对象,不要用eq或者equal判断字面量向量的相等性。

内容的提问来源于stack exchange,提问作者Pedro Delfino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 08:12:02