【问题标题】:how to specify element type in vector of sbcl (or common lisp)?如何在 sbcl(或 common lisp)的向量中指定元素类型?
【发布时间】:2014-01-11 15:27:58
【问题描述】:

我在 sbcl 1.1.14 中尝试了以下代码,但类型检查似乎忽略了向量元素的声明。

(defun test (vec)
  (declare (type (vector integer) vec))
  (format nil "~a~&" (elt vec 0)))

有什么提示吗?谢谢!

【问题讨论】:

  • 您能否详细说明类型检查忽略声明 的含义?当我运行您的代码并执行(test #(1 2 3)) 时,我得到1 的预期。当我做(test '(1 2 3)) 时,我得到了The value (1 2 3) is not of type (VECTOR INTEGER).,正如预期的那样。我正在使用sbcl 1.0.57 版。
  • @mrbatch try (test #('1 2 3)) 返回 '1 对我没有警告/错误(SBCL 1.1.14)
  • @verdammelt 啊,是的,我明白了。 (test #(a b c)) 也没有返回错误,只是 A

标签: types common-lisp sbcl


【解决方案1】:

首先请注意,标准 ANSI Common Lisp 不提供将声明作为类型检查。这是 CMUCL 引入的扩展。 SBCL 是 CMUCL 的后代。

Common Lisp 类型系统对向量和数组的工作方式有点不寻常。

元素类型

正在使用元素类型创建数组。这意味着 Lisp 系统将创建一个可以存储该类型元素的数组。但是 Common Lisp 并不要求每种元素类型都有专门的数组版本。如果数组的特殊版本不可用,则元素类型将升级为下一个“更大”类型。

元素类型升级示例

CL-USER 14 > (upgraded-array-element-type '(unsigned-byte 1))
(UNSIGNED-BYTE 1)

CL-USER 15 > (upgraded-array-element-type '(unsigned-byte 2))
(UNSIGNED-BYTE 2)

所以有针对(unsigned-byte 1)(unsigned-byte 2) 优化的数组版本。

CL-USER 16 > (upgraded-array-element-type '(unsigned-byte 3))
(UNSIGNED-BYTE 4)

哎呀!没有针对(unsigned-byte 3) 优化的数组。如果你请求这样一个数组,你会得到一个稍大的数组,(unsigned-byte 4)

CL-USER 17 > (upgraded-array-element-type '(unsigned-byte 4))
(UNSIGNED-BYTE 4)

CL-USER 18 > (upgraded-array-element-type '(unsigned-byte 5))
(UNSIGNED-BYTE 8)

CL-USER 19 > (upgraded-array-element-type 'integer)
T

上面显示没有特殊的整数数组。你会得到一个通用数组。

您的代码

(defun test (vec)
  (declare (type (vector integer) vec))
  (format nil "~a~&" (elt vec 0)))

所以你在这里的声明真的是这个意思:

变量vec 绑定到一个可以保存integer 数字的向量。

这并不意味着:

变量vec 绑定到一个只包含integer 数字的向量。

CL-USER 21 > (typep '#(a "b" #\c) '(vector integer))
T

上面在我的 Lisp 中返回 true,因为向量是一个通用向量,它可以存储整数。所以它检查向量的类型,但它并不关心向量的内容是否实际上都是整数类型。它只是说,向量可以包含整数。

基于谓词的类型检查

Common Lisp 允许类型声明使用谓词。

CL-USER 28 > (defun vector-of-numbers-p (vector)
               (and (typep vector 'vector)
                    (every 'integerp vector)))
VECTOR-OF-NUMBERS-P

CL-USER 29 > (typep '#(a "b" #\c) '(satisfies arrayp))
T

CL-USER 30 > (typep '#(a "b" #\c) '(satisfies vector-of-numbers-p))
NIL

CL-USER 31 > (typep '#(1 2 3) '(satisfies vector-of-numbers-p))
T

但是在编译时检查呢?应该不会吧。

【讨论】:

  • 非常感谢!非常清晰和翔实的解释。我现在对数组了解更多。这真的不简单。这样的设计很有趣,尽管通常需要具有一种特殊类型的元素的数组(向量),至少对于科学计算来说是这样。希望 common lisp 可以为任何类型提供专门的数组。
  • @user3185284:这需要什么?什么样的科学需要它?请注意,type 可以是“所有素数”或“所有至少有 4 扇门的红色汽车”。也许您正在考虑
猜你喜欢
  • 2016-10-27
  • 1970-01-01
  • 2019-12-28
  • 2015-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多