我们有以下内容:
CL-USER> (subtypep 'integer 'number)
T
T
CL-USER> (subtypep 'double-float 'number)
T
T
CL-USER> (subtypep 'vector 'array)
T
T
所以这个:
CL-USER> (subtypep '(vector integer) '(array number))
T
T
但我不明白:
CL-USER> (subtypep '(vector double-float) '(array number))
NIL
T
我使用SBCL 1.3.1.debian x86_64,以防这是依赖于实现的。谢谢!
答案 0 :(得分:6)
(array foo)
是否为(array bar)
的子类型取决于实现在内存中是否具有类型为foo
和bar
的值数组的压缩表示。如果实现对其中一个元素类型具有更紧凑的表示(例如,为了避免内存表示中的间接级别),则数组类型不兼容,因此subtypep
返回false。如果实现使用相同的压缩表示或通用表示,则subtypep
将返回true。
特别是,函数(lambda (foo bar) (subtypep `(array ,foo) `(array ,bar))
的行为依赖于实现。
例如,(array integer)
是SBCL和CLISP中(array number)
的子类型,但不是GCL中的子类型。 (array double-float)
是CLISP中(array number)
的子类型,但不是GCL或SBCL中的子类型。
答案 1 :(得分:4)
来自SUBTYPEP
:
因此,
(subtypep '(array T1) '(array T2)) => true
当且仅当
(upgraded-array-element-type 'T1) and (upgraded-array-element-type 'T2)
返回两个不同的类型说明符,它们总是引用相同的对象集。
以下是UPGRADED-ARRAY-ELEMENT-TYPE
返回的SBCL 1.3.7:
CL-USER> (upgraded-array-element-type 'double-float)
DOUBLE-FLOAT
CL-USER> (upgraded-array-element-type 'number)
T
我想如果我们尝试添加整数或复数,那么专门用于双浮点数的数组可能会表现不正常。规范并未要求实现保证在这种情况下子类型关系成立。
这与Covariance, Contravariance and Invariance间接相关:
作为源和接收器的可变数据类型应该是不变的。 [...] Cat []不能被视为动物[]。应该总是可以将狗放入动物[]。