6.57 arrays and copies of arrays (14.12.00)

6.57.1 Jan van den Heuvel

I’ve been doing some programming in Maple 6, involving manipulation of arrays of sets. ( If you want to know, the sets represent out- or in-neighbours of the vertices of directed graphs. ) While trying to figure out why I couldn’t get something to work, I encouraged some strange behaviour. Here is an example :

The following simple procedure takes as input an array, and just replaces its first element by an empty set.

clearset := proc(arrayset) 
    local a; 
    a := arrayset; 
    a[1] := {}; 
    eval(a); 
  end:
 

So lets take a small example.

> aset := array(1..2,[{1},{2}]); 
 
                          aset := [{1}, {2}]
 

And now run the procedure, with the expected outcome.

> clearset(aset); 
                              [{}, {2}]
 

But now the weird thing. Also the original array has changed. In other words, the procedure "clearset" has changed one of its input variables !!??

> eval(aset); 
                              [{}, {2}]
 

Now it may have something to do with my clumsy programming skills, but a similar example using arrays with numbers behaves different :

clearset2 := proc(arraynumbers) 
    local a; 
    a := arraynumbers; 
    a[1] := 0; 
    eval(a); 
  end:
 
> cset := [1,2]; 
                            cset := [1, 2] 
 
> clearset2(cset); 
                                [0, 2] 
 
> eval(cset); 
                                [1, 2]
 

Any explanations ?

A second, related question. Suppose I have an array, and I want to make a copy of it which doesn’t change.

With variables I would do

> a := 1; 
                                a := 1 
 
> b := eval(a); 
                                b := 1 
 
> a := 0; 
                                a := 0 
 
> b;
 

1 But with array this doesn’t work !?

> aa := array([1,2,3]); 
                           aa := [1, 2, 3] 
 
> bb := eval(aa); 
                           bb := [1, 2, 3] 
 
> aa[1] := 0; 
                              aa[1] := 0 
 
> eval(bb); 
                              [0, 2, 3]
 

How to do this instead ?

6.57.2 Robert Israel (15.12.00)

| But now the weird thing. Also the original array has changed. ...

Yes. The point is that := doesn’t make a copy. After a := arrayset, both a and arrayset have the same value, which is an array. Changes to the array will affect both.

| Now it may have something to do with my clumsy programming ...

It makes no difference whether the entries are sets or numbers.

| > cset := [1,2];
 

That’s not an array, it’s a list. Lists and arrays are quite different. An assignment to a list element, e.g. a[1]:= 0, makes a new copy of the list and assigns it to a.

| A second, related question. Suppose I have an array, ...

Carl DeVore and I have just had an extensive discussion in this list about copying arrays, rtables, procedures and modules. For an array, the simplest way is B:= copy(A).

see: Dynamic code with lexical variables (U. Klein)

6.57.3 Douglas Wilhelm Harder (15.12.00)

Use the copy command to make a copy of an array/matrix/table/vector or a Array/Matrix/Vector. This is not new to Maple6.

clearset := proc(arrayset) 
    local a; 
    a := copy( arrayset );   # Change 
    a[1] := {}; 
    eval(a); 
  end:
 

In your second example, you are using a list, not an array. If you were to use:

> cset := array( [1, 2] );
 

then you would get the same behaviour as with your first example.

For your last example, copy also works.

> aa := array([1,2,3]); 
 
            aa := [1, 2, 3] 
 
> bb := copy(aa); 
 
            bb := [1, 2, 3] 
 
> aa[1] := 0; 
 
              aa[1] := 0 
 
> print(bb); 
               [1, 2, 3] 
> print(aa); 
               [0, 2, 3]
 

6.57.4 Carl DeVore(18.12.00)

Have you considered using the networks package? Type ?networks for more info.

| > clearset := proc(arrayset)
 

You could just as well assign the element directly (no local variable needed):

clearset:= proc(a) a[1]:= 1; a end;
 

| But now the weird thing. Also the original array has changed. ...

It has only changed the contents on the variable, not the variable itself. It would be different if you tried assigning directly to a.

  a:= array(...whatever...);
 

would give you an error message inside the procedure.

The array is just a box. Changing the box is different from changing the contents of the box.

Here’s an analogy: Ernic and Christina are children each with a box of toys. Ernic’s box is red and has a loosely attached sign that says "Ernic’s toys". Christina’s is blue and has a loosely attached sign that says "Christrina’s toys". Ernic acquires a new toy and puts it in his box.

Is there any need for him to change the sign on his box in any way? Of course not. Christina decides that she would like a red box for her toys. She discusses it with Ernic and he decides that he would like a blue box, and they decide to trade boxes. (Whether they decide to trade the toys also really doesn’t matter to this analogy.) Should Ernic’s sign now be put on the blue box and Christina’s sign on the red box? Of course.

Think of the array name "a" as the sign on the box.

| Now it may have something to do with my clumsy programming ...

cset in not an array, it is a list. If you merely put something in square brackets, it is a list. For reasons that I don’t fully understand, the designers of Maple decided that a list is not "just a box". Even though Maple will allow it in this simple case, you probably shouldn’t be assigning to the elements of a list anyway. Weird things can happen that I won’t go into right now.

| A second, related question. Suppose I have an array, ...

That "eval" would only be needed in exceptional circumstances.

| But with array this doesn’t work !?

That command has only put a new, additional, sign on the box. Ernic and Christina decide to keep their toys in the same box and both signs are put on the one box. It has not created a new box. To create a new box, use the copy command:

   bb:= copy(aa);
 

Also, over the past week or so, Robert Israel, Helmut Kahovec, and myself have been discussing on this mailing list more efficient ways of copying various objects, including arrays.