Need for subvar ?



Wilhelm Haager <wilhelm.haager at htlstp.ac.at> writes:
> Is there any difference between subvar(A,i) and just A[i]?

I know of at least one important difference, shown below:

(%i2) robust_first_element(A) := subvar(A,1)$
(%i3) brittle_first_element(A) := A[1]$
(%i4) M[1] : 5$
(%i5) robust_first_element(M);
(%o5) 5
(%i6) brittle_first_element(M);
(%o6) 5
(%i7) A[1] : 11$
(%i8) robust_first_element(M);
(%o8) 5
(%i9) brittle_first_element(M);
(%o9) 11

As you can see here, both robust_first_element and brittle_first_element
work the same way if there is no global array A[].  However, if A[]
exists, then the A[1] in brittle_first_element will refer to the global
array, and not to the local parameter A.

The names of arrays, functions, and bare variables are each kept in
their own namespace.  For example, you can use a variable named "exp" to
store an expression, and that does not conflict with the built-in exp(x)
exponential function.  You could also have an array exp[].

In this case, the separation of namespaces implies that the A[1] within
the definition of brittle_first_element does not refer to that
function's formal parameter A, but instead the array A[].

However, as a convenience feature, if the array A[] does not exist, then
Maxima will try looking up A in the normal variable namespace.
Unfortunately, this "convenience" feature encourages the creation of
brittle code.

subvar(A,1), on the other hand, evaluates A as a bare variable, before
evaluating the array reference itself.

Similarly, consider:

(%i10) robust_assign_first_element(A, value) := arraymake(A,[1]) :: value$
(%i11) brittle_assign_first_element(A, value) := A[1] : value$
(%i12) A[1];
(%o12) 11
(%i13) M[1];
(%o13) 5
(%i14) robust_assign_first_element(M, 6);
(%o14) 6
(%i15) M[1];
(%o15) 6
(%i16) A[1];
(%o16) 11
(%i17) brittle_assign_first_element(M, 7);
(%o17) 7
(%i18) M[1];
(%o18) 6
(%i19) A[1];
(%o19) 7

     Best,
      Mark