types - 如何指定 sbcl(或 common lisp)向量中的元素类型?

标签 types common-lisp sbcl

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

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

有什么提示吗?谢谢!

最佳答案

首先请注意,标准 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绑定(bind)到一个可以保存整数数字的向量。

这并不意味着:

变量vec绑定(bind)到一个仅保存整数数字的向量。

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

但是在编译时检查呢?可能不是。

关于types - 如何指定 sbcl(或 common lisp)向量中的元素类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21064113/

相关文章:

macros - 什么是宏功能?

common-lisp - 如何利用 SBCL 提供的信号量来对抗竞争条件

emacs - 粘液 - 如何补偿最近可能发生的变化

lisp - 在 cygwin 上安装 sbcl

lisp - 以编程方式 defun 具有给定名称的函数

c++ - 数组是一种数据类型吗?

c# - 将 System.Type 转换为 T 参数

swift - 代表任何元组的类型?

lisp - 将点对转换为 LISP 中的双元素列表

python - <class 'str'> 和 <type 'str' > 有什么区别