[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Dynamic mutidimensional arrays

From: Benjamin Kowarsch
Subject: Re: Dynamic mutidimensional arrays
Date: Sun, 2 Apr 2023 02:58:41 +0900


On Sun, 2 Apr 2023 at 00:53, Gaius Mulley <> wrote:

I do see implementing open array variables could be an easy win 
(and fit with the current implementation of open array parameters).

Be careful not to overload the language with too many specific features.

It is generally a better strategy to devise more general facilities that allow the implementation of types as libraries and thus outside of the language, but do so in a way that permits the library defined types to be first class objects. In M2R10 we have strived to follow that strategy.

Initially, we only intended to find such a solution for the implementation of complex number types without the need to implement them in the language itself, but as we progressed, we found ways to make just about any library defined type a first class object and make it behave as if it was built-in.

To achieve this, three facilities must be available:

(1) a means for two kinds of opaque types, one statically and one dynamically allocatable
(2) a means to bind built-in syntax to the public interface functions and procedures of library defined types
(3) a differentiation of different categories of types in the type system so that different categories can follow different type regimes

For numeric types for example, the safest type regime is strict name equivalence, and it does not get in the way of getting work done. But for collection types, including array types, strict name equivalence makes less sense and it gets in the way more often than not. Instead, the most practical type regime for collection types is some form of structural equivalence, and this does not weaken type safety at all if done right.

Thus, we chose strict name equivalence for numeric types, we call them computational types, but a form of structural equivalence for collections, including array types. Two collections are (copy) compatible if the element types of their respective types are compatible.

COPY array := set;

equivalent to

array := {};
FOR elem IN set DO
  APPEND(array, elem)
END; (*FOR*)

assuming a one-dimensional array here for simplicity of illustration.

APPEND, INSERT and REMOVE are predefined (pervasive) procedures, and COUNT(), CAPACITY() and DIM() are predefined functions which library defined collection types can bind to, so that an invocation of these procedures can be translated into the appropriate library call within the library that implements the respective collection type. As a result, library defined arrays can be used exactly like arrays defined with the built-in ARRAY OF type constructor syntax, with the only difference being that they must be explicitly allocated before use.

All our built-in array types constructed with the ARRAY OF type constructor syntax are statically allocatable, with a specified capacity, but dynamically bounded. This way, any two arrays are compatible as long as their element types are and array slicing is part of the built-in syntax.

COPY arrayX := arrayY[n..m];

If you want to add multi-dimensional arrays, you may want to consider following a similar strategy.

Whatever you do, don't paint yourself into a corner from which you won't be able to escape later and regret it. ;-)

          VAR A: ARRAY OF ARRAY OF REAL ;  (* in *)
          VAR B: ARRAY OF REAL;            (* in *)
          VAR C: ARRAY OF REAL) ;          (* out *)
(* multiply matrix A[M,N] times vector B[N], result is vector C[M] *)
I would strongly advise against any scheme by which library/type users must remember type specific constructor procedures or functions. Likewise for type specific procedures for basic operations. That's just as horrible as PIM and ISO Modula-2's I/O nightmare with gazillions of specific write procedures like WriteThis, WriteThat, WriteYetAnotherThat. Sooner or later this sort of thing leads to more and more inconsistencies.

Instead, try to reuse syntax that is already built-in.

IMPORT Vector, Matrix;
VAR v1, v2 : Vector; m : Matrix;


NEW v2 := m * v1;

WRITE "v2 = ", v2;

RELEASE v1, v2, m;

And to do generic matrices ...

GENLIB Matrix4x5 FROM Matrices FOR
  valueType = LONGREAL;
  rows = 4; columns = 5

IMPORT Matrix4x5;


reply via email to

[Prev in Thread] Current Thread [Next in Thread]