[M3devel] ARRAY OF ARRAY (Re: A bizarre language quirk)

Henning Thielemann lemming at henning-thielemann.de
Sat Mar 24 19:49:30 CET 2018

On Fri, 23 Mar 2018, Rodney M. Bates wrote:

> On 03/21/2018 02:57 PM, Henning Thielemann wrote:
>>
>> On Wed, 21 Mar 2018, Rodney M. Bates wrote:
>>
>>> Modula3, 2.6.3 (Designators), concerning subscripting says:
>>>
>>> An expression of the form a[i_1, ..., i_n] is shorthand for
>>> a[i_1]...[i_n].
>>
>> I think I wrote earlier about this shorthand ...
>>
>> I found the following problem:
>>
>> ARRAY OF ARRAY OF Something
>>
>> is syntactically not quite a 2D-array since as it is written it suggests
>> that the sub-arrays may have different sizes.
>
> It never occurred to me that this syntax could suggest it could be a
> ragged array, probably because I was already familiar with the (fixed)
> array-of-array concept being truly 2D in Pascal and Modula2.

I did not have problems in understanding the Modula-3 report, instead I
consider it a flaw in the syntax and it has practical consequences. Why
can I choose in ARRAY OF ARRAY only the size of the outer array freely and
the sizes of the inner arrays are constrained? Where is the composability
of type constructors? And what is the size of the inner arrays if there
are no inner arrays? What else would be the type of a ragged array, if not
ARRAY OF ARRAY OF T?

In Haskell "Array Int (Array Int a)" would be actually a ragged array (in
Haskell all objects are actually pointers to objects) and a rectangular
2D-array would have the type "Array (Int,Int) a".

>> This has practical consequences. It would be no problem to have a 0-by-n
>> array. But Modula-3 fails
>> to determine the size of the second dimension of a 0-by-n array, because
>> LAST(a) is a range
>> violation in the first dimension.
>
> But a doesn't exist, so what would be a meaningful definition of its
> size or bounds?  Even if you could somehow define and discover it, you
> can't do anything else with a either.

I want to get the extent of the 2D array without accessing any element.
The array size must be stored separated from the elements anyway.

I encountered the problem when working with (row-major) matrices with zero
columns. E.g. this simple loop

FOR i:=FIRST(a) TO LAST(a) DO
sum:=0;
FOR j:=FIRST(a) TO LAST(a) DO
sum:=sum+a[j,i];
END;
b[i]:=sum;
END;

fails for a 0-by-n array because of the access to a. But technically
there is no need to reference a because the size of a is not stored
in a or any other a[i], but in 'a'.

Syntax suggests that NUMBER(a) and NUMBER(a) could be different but
they cannot. The syntax of 2D arrays in Modula-3 actually corresponds to
ragged arrays.

A syntax for rectangular two-dimensional arrays might be like:

ARRAY *,* OF T

or even mixed:

ARRAY *,[0..9],* OF T

A 3D array with ragged arrays in the last dimension would be:

ARRAY *,* OF ARRAY OF T

Elements might be accessed by

a[i,j]

It would still be useful to let a[i] denote a slice of the array. Then
a[i][j] would still be allowed. Also NUMBER(a[i]) would still be allowed
but it should not be necessary to access a[i]. Instead there might be a
variation of NUMBER, like:

NUMBER(a,0) and NUMBER(a,1)

to access the extents in the two dimensions without accessing a
potentially non-existent slice. The above loop would become:

FOR i:=FIRST(a,1) TO LAST(a,1) DO
sum:=0;
FOR j:=FIRST(a,0) TO LAST(a,0) DO
sum:=sum+a[j,i];
END;
b[i]:=sum;
END;

and it would work for 0-by-n arrays, too.