简单说,primitive 数据比如整数,浮点数,字符,相等测试和赋值非常直观,有着明显的语义和实现(位对比和复制)。对于更加抽象和复杂的数据类型,语义和实现上的问题就出现了。
比如考虑两个字符串是否相等:
- 是否别名
- 占据的空间是否全部按位相同
- 是否包含相同的字符序列
- 打印出来是否相同
第二条可能对于大多数程序过于低层;但是也表明,由于当前为使用的空间可能保留垃圾,比较也可能失败。其他三条可能都有自己的考虑,并且产生不同的结果。
存在引用的语言中,指向相同的对象相同被称为浅比较(shallow comparison),对象中内容相同被称为深比较(deep comparison)。对于复杂数据结构,深比较可能需要递归遍历。
在命令式语言中,赋值也区分浅赋值和深赋值。引用模型中,浅赋值就是引用引用相同对象。深赋值会创造一份完全的拷贝。在值模型中,浅拷贝会拷贝 b 的值,但是指针指向的内容不拷贝。
大多数语言支持浅比较和浅赋值。有些提供多种选择(尤其是 Python,Lisp 及其方言和 ML)。比如 Scheme 有三种相等测试
(eq? a b) ; do a and b refer to the same object?
(eqv? a b) ; are a and b known to be semantically equivalent?
(equal? a b) ; do a and b have the same recursive structrue?
深赋值相对罕见。主要用于分布式计算,尤其是 RPC 系统的参数传递中。
对于用户定义的抽象,没有单独的语言规范机制来规范相等测试或者赋值操作。通常允许程序员自定义这两种操作。