From: jlg@cochiti.lanl.gov (Jim Giles)
Newsgroups: comp.lang.misc
Subject: Re: Fortran90 and Arrays
Date: 6 Apr 92 19:27:14 GMT
Article-I.D.: newshost.1992Apr6.192714.4670
Organization: Los Alamos National Laboratory

In article <ROCKWELL.92Apr4183720@socrates.umd.edu>, rockwell@socrates.umd.edu (Raul Deluth Miller-Rockwell) writes:
|> [...]
|> By "maintenance cost" I meant a cost in maintaining the code -- time
|> required to analyze what's going on if an error is found and/or if an
|> enhancement is needed.

In which case, our extension already seems far superior to J.

Let the rest of the readers of this thread consider again:

      A(0: :2) = A(1: :2)

vs.
      A =: 2 # ((#A) $ 0 1) # A

The first requires usderstanding only the rules subscript triples.
The second requires understanding several different operations - most
of which you _don't_want_ the compiler to actually do because what
you want done is operationally most similar to the Fortran 90 version.

|> [... operators with precedence rules ...]
|> I don't think you've thought through the implications this will have
|> on meta-functional forms.
|> 
|> If nothing else, it'll be another set of arbitrary rules to memorize.

Untrue.  The rules of J are apparently that there is no precedence.
That will be true in Fortran 90 for all operators which are user defined.
So, for Fortran 90 there are no more rules to learn beyond what J requires
except for operators that already follow the `natural' precedence that
users actually desire.  These rules are certainly not arbitrary, but 
reflect the way people acually denote arithmetic operations even when
not programming.

Further, I don't think that it's much to a user's advantage to define
a lot of operators.  The function call syntax is better suited to those
operations which do not fit into the `natural' precedence scheme.

|> [...]
|>    I don't see the how this is true.  If the rank of the array is
|>    unknown, what operations can a recursive algorithm even apply to
|>    it?
|> 
|> addition, subtraction, multiplication, division, count atoms, count
|> dimensions, count items, various reductions, transposition, and
|> various forms of selection come to mind.

Some of these cannot be done on arrays of arbitrary rank.  Transposition,
for example, makes no sense for arrays of rank less than two.  So, the use
of these operations requires _some_ static knowledge of the rank of the
arguments.  This static knowledge should be encoded explicitly into
the function definition so that the optimizer has a chance of producing
good code. 

Other operations (like the arithmetical operations and the item counts)
don't depend on rank at all - they can be applied to the array as if
it were rank one.  Such a coercion in the procedure call mechanism
was already possible in Fortran 77.



Fortran 90's ability to define generic function interfaces will permit 
passing arrays of different rank in the same way.  Our extension will 
streamline the definition of generic procedures which differ only in 
their argument types, sizes, or shapes.

|> [...]
|> I guess I don't know what you mean by right-to-left default precedence
|> of the indices.

For example, you claim that the `catenate' operator can append a 
length 3 vector to a 3x3 array and produce a 4x3 array.  I seems
to me that the intuitive way for this to work should produce a 3x4 
result instead.  Seeing that this difference in intuition is not
reconcilable, I would would be willing to compromise by not having
_any_ default ordering.

|> [...]
|> where A had the declarations:
|>    |> >      A(i, j, k, l)
|>    |> >      A(i, j, k, l, w)
|>    |> >      A(i, j, k, l, w, x)
|>    |> >      A(i, j, k, l, w, x, y)
|> 
|> Obviously, any operations which only require that i, j, k, and/or l
|> covary could be meaningfully used. [...]


In which case your arguments to the function are _always_ rank 4.
It is their base `type' which varies from call to call.  The base
type of the array is:

      Type base_type = UNION
         real :: R
         real :: S(w)
         real :: T(w,x)
         real :: U(w,x,y)
      End base_type

Then the argument to the function is declared as:

      type(base_type) :: A(i,j,k,l)

Obviously, UNION is our extension.  Unions are always implicitly tagged.
Any operation which is defined on all the elements of a union is defined
on the union itself (so, for example, all the above can be elementally
added to any othe conformable object).  This use of union is simply
a short-cut for writing procedures which are generic in the types of
their arguments.

J. Giles
Newsgroups: comp.lang.misc