Paul Buckingham
Paul Buckingham

Reputation: 13

setf seems to change both its arguments when they are given by aref

In Lisp, I've defined an array a and then let b be equal to a. I now want to redefine an entry of b to be equal to a different entry in a, like this:

(setf a (make-array '(2 2) :initial-contents '((1 2) (3 4))))
(setf b a)
(setf (aref b 0 0) (aref a 0 1))

So now, b will be #2A((2 2) (3 4)), which is all well and good. But what puzzles me is that a is also now #2A((2 2) (3 4)).

My question is this: why has applying setf to an entry of b changed a as well? I can get around this by introducing an intermediate variable with (setf x (aref a 0 1)) and then applying (setf (aref b 0 0) x), but this seems like a strange workaround to me.

Upvotes: 1

Views: 33

Answers (1)

Jared Davis
Jared Davis

Reputation: 569

Your (setf b a) in the second line does what is sometimes called a shallow copy in other languages. That is, b does not become an independent copy of the array a, but rather becomes just another name for the exact same array. As a result, when you modify b, you are modifying a as well.

If you want b to be a true, independent copy ("deep copy") of the array, then you'll need to allocate a new array and copy the elements of a into it. One way to do this is for 1-dimensional arrays is with the copy-seq function. For fancier arrays you might also look at this question about how to copy 2d arrays which talks about some available libraries and approaches.

Upvotes: 2

Related Questions