Wer*_*dok 3 lisp arrays sbcl common-lisp multidimensional-array
考虑这个简单的例子:
(deftype image nil '(simple-array single-float (100)))
Run Code Online (Sandbox Code Playgroud)
这里我们定义一个类型的简写,这个类型是一个包含单个浮点数的数组.让我们尝试创建一个这样的:
(defparameter tmp
(make-array 100
:element-type 'single-float
:initial-element 0.0))
Run Code Online (Sandbox Code Playgroud)
让我们检查一下以防万一:
CL-USER> (type-of tmp)
(SIMPLE-ARRAY SINGLE-FLOAT (100))
Run Code Online (Sandbox Code Playgroud)
都好.让我们看看我们是否可以将这些小数组放在另一个数组中,以使检索更容易,而不是将所有内容放入一个单维数组中,最终让人头痛地计算访问索引.
(defparameter image-array
(make-array 10
:element-type 'image
:initial-element tmp))
Run Code Online (Sandbox Code Playgroud)
它不会失败,但检查以防万一:
CL-USER> (type-of image-array)
(SIMPLE-VECTOR 10)
Run Code Online (Sandbox Code Playgroud)
哎呀,这根本不是我们想要的.似乎这个新数组默认为默认元素类型:
CL-USER> (array-element-type image-array)
T
Run Code Online (Sandbox Code Playgroud)
这可能意味着应用程序现在必须不仅要检查容器数组元素,还要检查子数组的元素以及性能的所有后果.出现的问题是:
是否可以在SBCL中将类型化数组作为数组元素存储在另一个数组中?
编辑:恐慌可能有点太早,因为这会返回正确的类型:
CL-USER> (type-of (aref image-array 0))
(SIMPLE-ARRAY SINGLE-FLOAT (100))
Run Code Online (Sandbox Code Playgroud)
在这种情况下,为什么我们从中获取T元素类型(array-element-type image-array)?
有点背景ELEMENT TYPE实际意味着什么
如果给出一个元素类型,MAKE-ARRAY请求Common Lisp实现创建一个具有优化空间布局(!)的数组,该数组可能仅限于某些元素类型.您不需要为此元素类型获取数组,而是需要在此实现中为此元素类型最节省空间的数组.
对于数字,实现可能有比特的特殊版本,8比特字节,16比特字,32比特字和更多.
它可能有特殊版本的字符数组,如字符串
它可能具有一个或多个浮点数类型的特殊版本
是否有更多取决于您正在使用的实施.
对于没有特殊实现的任何元素类型,元素类型将升级到T.这意味着数组可以将所有类型的对象作为元素,并且更大的元素(如数组,字符串,结构,CLOS对象,...)将始终存储为指向堆上对象的指针.
某些实现的几个示例:
整型
CL-USER> (upgraded-array-element-type '(integer 0 1))
(UNSIGNED-BYTE 1)
CL-USER> (upgraded-array-element-type '(integer 0 2))
(UNSIGNED-BYTE 2)
CL-USER> (upgraded-array-element-type '(integer 0 3))
(UNSIGNED-BYTE 2)
CL-USER> (upgraded-array-element-type '(integer 0 4))
(UNSIGNED-BYTE 4)
CL-USER> (upgraded-array-element-type '(integer 0 5))
(UNSIGNED-BYTE 4)
CL-USER> (upgraded-array-element-type '(integer 0 7))
(UNSIGNED-BYTE 4)
CL-USER> (upgraded-array-element-type '(integer 0 8))
(UNSIGNED-BYTE 4)
CL-USER> (upgraded-array-element-type '(integer 0 15))
(UNSIGNED-BYTE 4)
CL-USER> (upgraded-array-element-type '(integer 0 16))
(UNSIGNED-BYTE 8)
CL-USER> (upgraded-array-element-type '(integer 0 256))
(UNSIGNED-BYTE 16)
CL-USER> (upgraded-array-element-type '(integer 0 4423423))
(UNSIGNED-BYTE 32)
CL-USER> (upgraded-array-element-type '(integer 0 4423423423423))
(UNSIGNED-BYTE 64)
CL-USER> (upgraded-array-element-type '(integer 0 4423423423423423423423423423423))
T
Run Code Online (Sandbox Code Playgroud)
人物
CL-USER> (upgraded-array-element-type 'character)
CHARACTER
Run Code Online (Sandbox Code Playgroud)
花车
CL-USER> (upgraded-array-element-type 'single-float)
SINGLE-FLOAT
CL-USER> (upgraded-array-element-type 'long-float)
DOUBLE-FLOAT
Run Code Online (Sandbox Code Playgroud)
排列
CL-USER> (upgraded-array-element-type 'array)
T
Run Code Online (Sandbox Code Playgroud)
即使你要求更多特定版本的数组作为元素,你很可能得到T答案.
什么时候要求特殊阵列
最重要的原因是节省空间.如果只有位,则通用数组可以存储位,但位向量将节省大量空间.
但是:具有特殊元素类型的数组的操作可能会更慢.在安全代码的运行时,可能存在附加类型检查,并且更改/读取元素的操作可能需要较慢的处理器指令.
Common Lisp数组的局限性
因此,Common Lisp没有针对结构,向量,CLOS对象等数组的优化存储布局.由于存储了每个元素的指针,访问总是需要间接,并且没有任何东西可以保证这些对象存储在线性中记忆中的顺序.以线性顺序存储的是数组中指向它们的指针.
检查您的实现是否已针对float(single,double,long,...)数组优化了空间布局.
多维数组
Common Lisp支持最多的真正的多维数组ARRAY-RANK-LIMIT(ABCL在我的ARM上有8个维度,其他一些实现支持更多维度).这些多维数组也可以具有专门的元素类型.
| 归档时间: |
|
| 查看次数: |
222 次 |
| 最近记录: |