(elisp) Vector elements of vectors

I will construct a two dimensional array (matrix) consisting of a vector of vectors:

(setq zero-row [0 0 0 0 0])
  => [0 0 0 0 0]

(setq zero-mat (make-vector 4 zero-row))
  => [[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]

      

I'll put the element on row 2, column 3 (at index 0) to 42, replacing row 2 with a vector containing the changed element:

(aset zero-mat 2 [0 0 0 42 0])
  => [0 0 0 42 0]

zero-mat
  => [[0 0 0 0 0] [0 0 0 0 0] [0 0 0 42 0] [0 0 0 0 0]]

      

He works.

Next, I'm trying to build a function that uses this approach to set the (i, j) th element in a two-dimensional array like this:

(defun matrix-set (mat i j elt)
"Set the (i, j)-th element of mat to elt. mat is a vector of the row vectors. Indexing is 0-based in each component."
(let ((vect (aref mat i)))
   (aset vect j elt)
   (aset mat i vect)
   mat))

      

But this doesn't work:

(setq zero-row [0 0 0 0 0])
  => [0 0 0 0 0]

(setq zero-mat (make-vector 4 zero-row))
  => [[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]

(matrix-set zero-mat 2 3 42)
  => [[0 0 0 42 0] [0 0 0 42 0] [0 0 0 42 0] [0 0 0 42 0]]

      

It looks like all the rows in the array are associated with the same vector, so changing that vector changes all the rows.

So, two questions: (1) Why does this happen in the second case, but not in the first? (2) How can I fix this (so that I can access the (i, j) th record of the 2-dimensional array represented this way)?

(I originally wrote a small routine to add two matrices represented as vectors of vectors as above and ran into the same problem. I think the above example might make the problem clearer.)

+3


source to share


1 answer


In the first case, you are replacing an element in the "outer" vector with another vector (while the other three "inner" vectors still point all to the same element). In the second case, you are replacing an element in the "inner" vector (and you only have one inner vector, duplicated four times, according to your example. A simple way to initialize a vector for different different vectors would be something like this:

(let ((i 0) (new-vector (make-vector 4 nil))
 (while (< (progn (aset new-vector i (make-vector 5 0))
                  (incf i))
           (length new-vector)))

      



Sorry if there are any typos, wrote it locally. But the idea should be simple enough to figure it out.

+3


source







All Articles