From: rockwell@socrates.umd.edu (Raul Deluth Miller-Rockwell)
Subject: Re: Fortran90 and Arrays
Organization: Traveller
	<ROCKWELL.92Apr4183720@socrates.umd.edu>
	<1992Apr6.192714.4670@newshost.lanl.gov>
Date: Tue, 7 Apr 1992 04:08:31 GMT

I wrote:
>  |> 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.

Jim Giles:
>  In which case, our extension already seems far superior to J.

Not to me it doesn't.

>  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.

You're leaving out the big picture here, which is: why are you doing
this operation in the first place?  Chances are, there are other ways
of expressing the algorithm which don't involve this sort "partial
array mangling".

Personally, I don't find either expression very suggestive of
anything -- if I encountered either of these expressions in code I was
responsible for enhancing, I'd prefer to rip it out and replace the
entire algorithm.  Except, in fortran, I probably wouldn't have any
better options.

>  |> [... 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.

Untrue.  For example, conjunctions have precedence over verbs.

>  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.

So, what's the precedence of subtraction vs greatest common
denominator?  How about antibase vs nth root?  Or are you going to say
that people shouldn't be allowed to use operators for things which
aren't included in Fortran?

>  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 disagree.  But I'd probably agree if I had to use Fortran's crippled
data types -- there's just too much bookkeeping required for operator
syntax to be very useful.

>  |> [...]
>  |>    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.

It's an identity operation on arrays of rank less than two.  That's
different, in my opinion, from "makes no sense".

>  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.

Most likely the static information will be explicitly encoded into
either the function definition or the code which uses that definition.
If not, and if the user determines that that particular function is
time critical, then the user can nail down additional aspects of the
function.  But remember that usually only a small fraction of any
major piece of code is time critical.

>  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.

Well, this depends on your definition of an item.  I use 'item' to
mean a sub array (whose dimension may be obtained by dropping the
first dimension of the original array).  I use the term 'atom' to mean
a scalar element of an array.  For example, if I've a rank 5 array, I
may wish to add each of its items a rank 4 array.

>  |> 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.

As I understand it, this definition has nothing to do with the
intuition of somebody who's never learned what the operation does.

catenate will append two arrays of the same rank, or it will append an
item onto an array.  If you wish to append a length three vector to a
3x3 array, you would need to define an operation which appends each
item of the 3 element vector to the corresponding item of the 3x3
array.  This might be done as follows:
>       vector   ,"_1  array

Here, 'comma rank minus-one' defines the desired operation.

The advantage of this rule is 'rank' has a consistent and easily
understandable definition which is usable with any operation in the
language.  No exceptions are needed.

>  |> [...]
>  |> 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)

Why bother?  You've added verbosity, but I don't see that you've added
functionality.  I'd prefer to use pairs of sequences to represent my
array and build my own operations -- that would be much more modular
than this requirement that I write out declarations to package some of
my dimensions just to execute one or two functions.

Your notation concentrates so much on the special cases I'd be
constantly re-stating similar algorithms in different ways, to get
them past the quirks of your language.  This doesn't leave a lot of
time or energy to analyze the overall problem, or to come up with
cleaner designs.

-- 
Raul Deluth Miller-Rockwell                   <rockwell@socrates.umd.edu>
Xref: sparky comp.lang.misc:1573 alt.sources.d:548