首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么常量不能在通用Lisp类型说明符中用作数组维度?

为什么常量不能在通用Lisp类型说明符中用作数组维度?
EN

Stack Overflow用户
提问于 2013-09-30 03:19:38
回答 5查看 1K关注 0票数 6

至少在某些类型说明符中,Common的某些实现不允许将用户定义的常量用作数组维度。例如,在SBCL中,以下代码:

代码语言:javascript
复制
(defconstant +len+ 3)

(defun foo (x) 
  (declare (type (simple-array fixnum (+len+)) x))
  x)

生成此错误:

代码语言:javascript
复制
; in: DEFUN FOO
;     (TYPE (SIMPLE-ARRAY FIXNUM (+LEN+)) X)
; 
; caught ERROR:
;   bad dimension in array type: +LEN+

为什么?用户定义的常量不能用于类型说明符,这似乎令人惊讶,因为希望能够使用某种全局定义来协调多个类型说明符。我知道类型说明符需要在编译时完全可以理解。但是,我认为编译器可以用它们的字面值替换用defconstant定义的符号。我原以为这是defconstant的目的之一。(到目前为止,我一直未能从通用Lisp、CLTL2、SBCL手册或谷歌发现的内容中更深入地理解这个问题。我怀疑答案是以某种形式存在的.)

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-09-30 06:55:53

我想像这样的东西会起作用:

代码语言:javascript
复制
(defconstant +len+ 3)

(deftype len-3-fixnum-array () `(array fixnum (,+len+)))

(defun foo (x)
  (declare (type len-3-fixnum-array x))
  (print x))

(foo (make-array 3 :element-type 'fixnum))
;; #(0 0 0)

(foo (make-array 4 :element-type 'fixnum))
;; The value #(0 0 0 0) is not of type (VECTOR FIXNUM 3).
;;    [Condition of type TYPE-ERROR]

但是,您需要记住,类型注释只是建议,编译器可以完全忽略它们。

也就是说,问题不在于不能在declare形式中使用常量,而是它的作用就好像它被引用了一样,所以那里的常量不计算为3,它只是保留符号+len+

票数 6
EN

Stack Overflow用户

发布于 2015-12-01 12:35:43

对于2D数组,我也遇到了同样的问题:

代码语言:javascript
复制
(defconstant board-width  4)
(defconstant board-height 3)

(setq *board* (make-array '(board-width board-height) :initial-element 0))

我总是会犯错误

代码语言:javascript
复制
The value BOARD-WITH is not of type SB-INT:INDEX.

所以我把最后一行改为:

代码语言:javascript
复制
(setq *board* (make-array (list board-width board-height) :initial-element 0))

而且效果很好。

票数 6
EN

Stack Overflow用户

发布于 2013-09-30 06:56:07

如果您查看ANSI CL规范,类型的语法是明确定义的。对于简单阵列

代码语言:javascript
复制
simple-array [{element-type | *} [dimension-spec]]

dimension-spec::= rank | * | ({dimension | *}*) 

其中:

代码语言:javascript
复制
dimension---a valid array dimension.

element-type---a type specifier.

rank---a non-negative fixnum.

然后将valid array dimension解释为一个固定值。

simple-array类型声明中没有变量或常量标识符。类型声明有自己的语法,不计算或类似。它们是类型表达式,可以出现在特殊位置的代码中(->声明)。

您可以使用DEFTYPE 来创建新的类型名称,但是可以使用这些名称.

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19085980

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档