From: jlg@cochiti.lanl.gov (Jim Giles)
Subject: Re: Types, arrays, generality, and notation (was: Fortran90 and Arrays)
Organization: Los Alamos National Laboratory
Date: Fri, 10 Apr 1992 10:34:45 GMT

In article <ROCKWELL.92Apr10011141@socrates.umd.edu>, rockwell@socrates.umd.edu (Raul Deluth Miller-Rockwell) writes:
|> [...]
|>    |>    How would this have been different if I had used the example:
|>    |>          A(0: :2) = B(1: :2)
|> [...]
|>
|>     A =. (B {~ 1 + B step 2)   (A step 2) } A
|> [...]
|>    step   =.  'where: x. $ y. {. 1'     :11
|>    where: =.  'y. #   i. # y.'          :11

An awful lot of work for such a simple concept.  And, once again,
it's a long way from what you actually want to have happen operationally.
So, you optimizer better be really good.  It's also an awful long way
from the mental model of the operation that users have.  

In any case (question addressed to other readers), how many users
really prefer the J version to the Fortran version?

|> [...]
|> Also, note that although I've not made any explicit declarations about
|> the sizes of A and B, there are a number of such assertions implicit
|> in the above code.  The above code will work unless B has an even
|> number of elements, nor will it work unless A step 2 is identical to B
|> step 2.

Well, at least you appear to do the right conformability tests.  But,
since you have no declarations, there's not a way for the compiler to
apply these constraints until run-time - unless you have a _really_
good data flow analysis built into the compiler.  Of course, the Fortran
compiler has the same problem in procedures where A and B are passed
as arguments with unspecified length.

|> [...]
|> Yes.  It gets worse: J doesn't allow you to change a single element of
|> an array without respecifying the entire array.

For those algorithms in which whole array is going to modified in
essentially the same way, this is actually the desired operation.
That's why Fortran 90 added the whole array features it has.  It's
part of the motivation for our proposed extensions as well.  But,
modifying single elements in an aggregate is another fairly simple 
operation which is fairly common - so it should be simple to denote.

|> [... A + B ...]
|> First off, you are correct.  '+' is never overloaded for non-numeric
|> data.  So, yes, the compiler can always tell at compile time that both
|> A and B obey this constraint.

Your conclusion doesn't follow from the premise.  The fact that `+' is
defined only on numeric data tells the compiler that A and B are 
_supposed_ to be numeric.  It does not help in enforcing that.  A and
B may be assigned to _anything_ and such assignments may be run-time
dependent.

|> [...]
|> Of course, what I've not mentioned is that there is nothing in the
|> above expression to determine whether A and B represent numeric _data_
|> or functions returning numbers.  But if that information is not
|> available to the compiler then A and B must be undefined, and the
|> compiler is justified in refusing to compile this expression.

Oh?  So even if A and B _may_ be correct, if the compiler can't tell
for sure it refuses to accept the expression?  That _may_ actually
be a satisfactory rule - I'll have to think about it.

|> [...]
|> You can define an identifier to represent    f @only_vector:

Good.  One down and one to go.  If you can invent a similar mechainsm
to guard against undesired assignments you've got the whole thing.

|> [... using constraints on functions to enforce constraints on 
|>      other identifiers ..]
|> If assignments to x would result in the constraint being violated then
|> those assignments can be prohibited.  This depends, of course, on the
|> design of the compiler.  And, of course, on the topology of the
|> constraint.

I would be very surprised if this were true.  I suspect that the
error message would point to the function invocation and not the 
assignment as the culprit.  It would say (at the site of the
function invocation) that you were trying to pass an invalid
argument.  This could be quite far (in both time and code) from
the assignment which causes the problem.

|> [...]
|>    |> The type of an identifier can be determined from the expression
|>    |> used to declare it.  [...]
|> 
|>    Which is _not_ locally visible at the site of the use of the
|>    identifier, nor is it in some cannonical place (like the beginning
|>    of the present module or procedure).  It can be _anywhere_!
|> 
|> Well, in principle, yes.  In practice, no.

I suspect that working as a help-desk consultant has given me a rather
different perspective on what happens in practice than you have.

|> [... typed assignment ...]
|> 
|> set_X =.  'X =: invalid: ^: not_integer:    y.' : ''
|> 
|> You might like to think of ^: as the word 'IF'...

Ok.  So I have to define my own assignment for every variable 
I introduce.  This is an improvement?  Further, it doesn't really
apply the constraint I asked for - it only does so if I always 
remember to assign only with my private assignment syntax.

Note: I really am making an effort to cut the size of these
articles down.

J. Giles
Newsgroups: comp.lang.misc,comp.lang.functional,comp.object