在一種語言只有一維數組(或向量)是創建載體向量。
這裏是一個簡單的實現這一招(非常不適合生產使用!)中的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