Re
> (%i2) m2:addrow(m1,[7,8,9]);
> (%i3) m2[1][1]:0$
modifies m1
Alas, Maxima is quite incoherent in this area. It does whatever is
convenient for the underlying implementation. Since a matrix is
represented as a list of rows, it shares the rows when they are
manipulated:
m1: matrix([1])
r1: m1[1] => [1] vector
r1[1]: 2 $
m1 => [ 2 ] shared representation
m1: matrix([1])
r1: row(m1,1) => [ 1 ] -- note that result is a
1x1 *matrix*, not a vector
r1[1,1]: 2 $
m1 => [ 2 ] shared representation
m1: matrix([1])
c1: col(m1,1) => [ 1 ]
c1[1,1]: 8 $
m1 => [ 1 ] not shared representation
Even though this is semantically incoherent, it is sometimes practically useful.
Always treating matrices and their parts as fresh, unshared objects by
copying would certainly be easy to implement. However, it is
inconsistent in a different way. Consider a list of lists [ [ 2 ],
[3, 4] ] (not a matrix). This can be treated as a data structure (as
opposed to a mathematical object), in which case it is very natural
for parts of the structure to be shared.
Always treating matrices and their parts as mutable objects would be
much harder to implement. A special representation would have to be
defined for matrix columns since there is no straightforward way to
share structure. Other languages do support the notion of 'slices'
(shared submatrices), some rather sophisticated. This seems like a
lot of complication. If at some point we do integrate with a
full-featured linear algebra package, or a language supporting slices,
we should probably implement a compatible notion of slices. Until
then, I think the right attitude is to recommend that users treat
matrices, rows, and columns as immutable, and simply never assign to
their subparts -- unless they *really know* what they're doing....
-s