在一种语言只有一维数组(或向量)是创建载体向量。
这里是一个简单的实现这一招(非常不适合生产使用!)中的elisp:
(defun make-simple-array (dims &optional init)
;; make n-dimensional array, represented as a vector of vectors (of
;; vectors ...).
(if (null (cdr dims))
(make-vector (car dims) init)
(let* ((d1 (car dims))
(dt (cdr dims))
(v (make-vector d1 nil))
(i 0))
(while (< i d1)
(aset v i (make-simple-array dt init))
(setq i (1+ i)))
v)))
(defun simple-array-ref (a indices)
(if (null (cdr indices))
(aref a (car indices))
(simple-array-ref (aref a (car indices)) (cdr indices))))
(defun simple-array-set (a indices newval)
(if (null (cdr indices))
(aset a (car indices) newval)
(simple-array-set (aref a (car indices)) (cdr indices) newval)))
这种方法是简单的,但结果在可怕的地方:一个数组的元素都可以散在那个地方。更好的方法是分配一个大的矢量,然后计算它中的元素的位置。这就是任何严格的数组实现都能工作的方式。
对于hack值,这里是一个原始的和部分的实现,它将数组作为一个大向量并计算位置。在这个实现中,数组被存储为(v . factors)
的缺点,其中factors
是您计算索引到v
所需的预先计算的索引因子。此实现至少有两个问题:
- 阵列不知道自己的尺寸:您可以从指数的因素和向量的长度计算,但我懒得实现这一点;
- 尺寸没有被选中,所以如果你有一个2x2数组,那么你可以访问由
(0 2)
索引的元素,这实际上是由(1 0)
索引的元素。
无论如何,这里是一个实现。
(defun compute-flat-array-total-size (dimensions)
;; this is in fact (reduce #'* dimensions), but elisp
(let ((s 1))
(mapc (lambda (d) (setq s (* s d))) dimensions)
s))
(defun compute-flat-array-index-factors (dimensions)
(cond ((null dimensions)
'(0))
((null (cdr dimensions))
'(1))
(t (let ((ftail (compute-flat-array-index-factors (cdr dimensions))))
(cons (* (car dimensions) (car ftail))
ftail)))))
(defun compute-flat-array-index (indices factors)
;; Again, elisp sucks: you can't even use mapc here
(let ((index 0)
(itail indices)
(ftail factors))
(while (not (null itail))
(when (null ftail)
(error "too many indices"))
(setq index (+ index (* (car itail) (car ftail)))
itail (cdr itail)
ftail (cdr ftail)))
(unless (null ftail)
(error "two few indices"))
index))
(defun make-flat-array (dimensions &optional init)
;; a flat array is a cons of a vector of its contents and a list of
;; index factors.
(cons (make-vector (compute-flat-array-total-size dimensions) init)
(compute-flat-array-index-factors dimensions)))
(defun flat-array-ref (fa indices)
(aref (car fa) (compute-flat-array-index indices (cdr fa))))
(defun flat-array-set (fa indices newval)
(aset (car fa) (compute-flat-array-index indices (cdr fa)) newval))
来源
2017-05-14 21:27:21
tfb