With the list assignment (see List Assignment, Add, Append) it is possible to change a list. The ability to change an object is only available for lists and records. This section describes the semantic consequences of this fact.
You may think that in the following example the second assignment changes the integer, and that therefore the above sentence, which claimed that only lists and records can be changed is wrong
i := 3; i := i + 1;
But in this example not the integer 3
is
changed by adding one to it. Instead the variable i
is changed by assigning the value of i+1
, which happens to be
4
, to i
. The same thing happens in the following
example
l := [ 1, 2 ]; l := [ 1, 2, 3 ];
The second assignment does not change the first list, instead it assigns a
new list to the variable l
. On the other hand, in the following
example the list is changed by the second assignment.
l := [ 1, 2 ]; l[3] := 3;
To understand the difference first think of a variable as a name for an
object. The important point is that a list can have several names at the same
time. An assignment var := list;
means in
this interpretation that var is a name for the object list.
At the end of the following example l2
still has the value
[ 1, 2 ]
as this list has not been changed and nothing else has
been assigned to it.
l1 := [ 1, 2 ]; l2 := l1; l1 := [ 1, 2, 3 ];
But after the following example the list for which l2
is a name
has been changed and thus the value of l2
is now [ 1, 2, 3
]
.
l1 := [ 1, 2 ]; l2 := l1; l1[3] := 3;
We shall say that two lists are identical if changing one of them by a list assignment also changes the other one. This is slightly incorrect, because if two lists are identical, there are actually only two names for one list. However, the correct usage would be very awkward and would only add to the confusion. Note that two identical lists must be equal, because there is only one list with two different names. Thus identity is an equivalence relation that is a refinement of equality.
Let us now consider under which circumstances two lists are identical.
If you enter a list literal than the list denoted by this literal is a new
list that is not identical to any other list. Thus in the following example
l1
and l2
are not identical, though they are equal
of course.
l1 := [ 1, 2 ]; l2 := [ 1, 2 ];
Also in the following example, no lists in the list l
are
identical.
l := []; for i in [1..10] do l[i] := [ 1, 2 ]; od;
If you assign a list to a variable no new list is created. Thus the list
value of the variable on the left hand side and the list on the right hand
side of the assignment are identical. So in the following example l1
and l2
are identical lists.
l1 := [ 1, 2 ]; l2 := l1;
If you pass a list as argument, the old list and the argument of the
function are identical. Also if you return a list from a function, the old
list and the value of the function call are identical. So in the following
example l1
and l2
are identical list
l1 := [ 1, 2 ]; f := function ( l ) return l; end; l2 := f( l1 );
The functions Copy
and ShallowCopy
(see
Copy and ShallowCopy) accept a list and return a new list that is equal to
the old list but that is not identical to the old list. The
difference between Copy
and ShallowCopy
is that in
the case of ShallowCopy
the corresponding elements of the new
and the old lists will be identical, whereas in the case of Copy
they will only be equal. So in the following example l1
and
l2
are not identical lists.
l1 := [ 1, 2 ]; l2 := Copy( l1 );
If you change a list it keeps its identity. Thus if two lists are identical
and you change one of them, you also change the other, and they are still
identical afterwards. On the other hand, two lists that are not identical
will never become identical if you change one of them. So in the following
example both l1
and l2
are changed, and are still
identical.
l1 := [ 1, 2 ]; l2 := l1; l1[1] := 2;