The Racket Reference阅读笔记。
4.1 Equality
等同性在概念上是指判定两个量值是否相等。但这看似容易,实则很难,因为不同类型的量值有不同的等同性要求。为此,Racket提供了三级等同性判定:
- eq?,判定两个量值是否指向同一个标的。问题是,如果两个量值具有相同的内容,但是分属不同的标的,eq?的判定会失败。失败的例子:
(eq? (expt 2 100) (expt 2 100))
(eq? (mcons 1 2) (mcons 1 2))
- eqv?,在eq?的基础上增加了对字符和数值类型的特殊处理,对于内容为字符串和数值的标的,eqv?会检查其内容,并根据内容做出等同性判定,但eqv?的问题是不会对复合结构所包含的子内容进行检查。
- equal?,在eqv?的基础上,增加了对这些类型的特殊处理:字符串,字节串,子对,可变更子对,串列,封箱,哈希表,以及可检视的结构类型。
- 即便复合类型的内容包含引用回环,equal?也能正确处理
- 对于结构类型,可以通过gen:equal+hash以及prop:impersonator-of对其行为进行自定义
4.1.1 Object Identity and Comparisons
eq?适合用在与定性更新(更新的效果在所有地方都可能)的场景中,因为与定性更新产生新的标的对照。
但有些情况下,eq?不适用,因为什么适合该生成新的标的,什么适合不生成新的标的并没有明确的定义,编译器可以根据自己的优化上的需要自行决断。有时候相同的操作,比如(+ 1 2)
会返回相同内容的不同标的。另外一个例子,lambda构造的运算有可能生成新的执行决标的,也有可能重用旧标的。
需要查看每种数据类型的说明才能知晓其在eq?的具体表现。
4.1.2 Equality and Hashing
所有的课比较的量值都至少有一个哈希码,用fixnum表示的整型。对其的要求是同样的量值必须有同样的哈希码。但是不同的量值也可能有相同的哈希码。
相关执行决
(equal-hash-code v) → fixnum?
- 能够处理引用回环
- 可以适用gen:equal+hash自定义
- 读取过程,对于相同的字符输入,应有相同的输出
- equal?判定为相同的量值返回的哈希码必须也相同
(equal-secondary-hash-code v)
- 额外的哈希码,用于双重哈希的场景
- 如果不需要双重哈希,那么可能返回和equal-hash-code相同的值
(eq-hash-code v)
- eq?判定为相同的量值返回的哈希码必须也相同
(eqv-hash-code v)
4.1.3 Implementing Equality for Custom Types
gen:equal+hash
,用于给结构类型自定义哈希功能- equal-proc
- hash-proc
- hash2-proc
prop:equal+hash
,废弃不用
(本篇完)