From: heydon@src.dec.com
Subject: Re: structural equivalence ==> no referential transparency
To: comp.lang.modula3.usenet
Cc: sullivan@teal.csn.org
Organization: DEC Systems Research Center
X-In-Reply-To: Message of 24 Jan 93 16:52:42 GMT
    from sullivan@teal.csn.org (Steve Sullivan)
    <C1DAw0.ILz@csn.org>
Date: Sun, 24 Jan 93 16:46:52 -0800
X-Received: by pebbles.pa.dec.com; id AA01319; Sun, 24 Jan 93 16:46:52 -0800
X-Mts: smtp

Steve Sullivan (sullivan@teal.csn.org) writes:

> Main proc:
>  avec: ARRAY {1..100} OF LONGREAL;
>  ...
>  x = subproc( avec, k);
>
> subproc( avec, k):
>   v = avec[k]         (* will access element k+1 *) 
>
> Although Modula 3 does have FIRST and LAST functions, they
> seem more like afterthoughts than features:  even if the
> above subproc were coded   v = avec[FIRST(avec)-1+k],
> the subproc must still know the base of avec (hardcoded as "1").
> And in any event "avec[FIRST(avec)-1+k]"
> is far less clear to the reader than  "avec[k]".

Modula-3 makes a distinction between *fixed* an *open* arrays. A 
fixed array declaration includes an index type, while an open array 
declaration does not. The index type of an open array is [0..n-1], 
where "n" is the run-time length of the array, so the first element 
has index 0. You left out the type declarations for the "avec" and 
"k" formal parameters to the "subproc" procedure in your example, 
but I'm guessing that you meant for "avec" to be declared as an open 
array like this (I've changed the names of the variables in "subproc" 
to avoid confusion): 

  VAR
    avec: ARRAY [1..100] OF LONGREAL;
    k: [1..100];
    x: LONGREAL;

  PROCEDURE subproc(avec2: ARRAY OF LONGREAL; j: CARDINAL): LONGREAL =
    VAR v: LONGREAL; BEGIN
      v := avec2[j];
      RETURN v
    END subproc;

  BEGIN
    x := subproc(avec, k)
  END Main.

As Steve points out, this code will assign "x" the value "avec[k+1]". 
The problem is that he has not given a specification for "subproc". 
If he did, it would state that "subproc" returns the value of "avec2" 
at zero-based index "j". Therefore, to use the procedure correctly, 
we must convert the actual argument "k" to a zero-based index in 
the main body, like this: 

  BEGIN
    x := subproc(avec, k - FIRST(avec))
  END Main.

There is no way we can get around forcing such a conversion, since 
the actual parameter "avec" and the formal parameter "avec2" have 
different types. 

> However, for me their decision
> not only invalidates all use of enumerated index sets (they
> can't be used in subprocs), but destroys the usefulness of
> subprocs for handling arrays of any sort.

Formal array arguments may certainly be fixed. For example, if we 
had instead given the following signature to "subproc", in which 
the array argument is a fixed array: 

  PROCEDURE subproc(avec2: ARRAY [1..100] OF LONGREAL; j: CARDINAL):
      LONGREAL =
    VAR v: LONGREAL; BEGIN
      v := avec2[j];
      RETURN v
    END subproc;

then the arrays "avec" and "avec2" would have the same type, and 
so we would not need to convert the index argument "k" in the call 
to "subproc" by subtracting "FIRST(avec)". The limitation to using 
fixed arrays as formal procedure arguments is that such procedures 
can only be called with arrays of the specified length (or shape, 
for multi-dimensional fixed arrays). 

See pgs 14-15 of Systems Programming with Modula-3 (SPwM3) for definitions 
of fixed and open arrays; pg 24 for a definition of when one array 
type is a subtype of another; and pg 26 for when one array type is 
assignable to another. It is interesting to note that two one-dimensional 
fixed arrays are subtypes of each other if they have the same base 
type and the *number* of elements in their respective index types 
are the same.

Allan Heydon					heydon@src.dec.com
DEC Systems Research Center			(415) 853-2142
130 Lytton Ave.
Palo Alto, CA 94301
Newsgroups: comp.lang.modula3