Hallo Andreas,
thanks for the feedback, parts of my answer below in your text.
I am fully aware about (most of) the current features of the language (at least I hope so :-)
For me there is a inconsistency in the ISO approach of mutidimensional array ...
- you can use 1-dimensional open array parameters and you can allocate the space for them in the calling program or procedure
- we have multiply dimensional open array parameters for procedures
- but we can only use fixed sized multiple-dimensional arrays to hand over
- even in case of 1-dimensional arrays we cannot use "HIGH" to check if the dimension of the actual parameter handed over is sufficient (at least if I do not want to make everything based on records having a data field and a size field.
Below a short sample (which, for the reasons give about, is sub-optimal).
With "my" approach one could hand over proper "high" parameters to the procedure called for 1 or multi-dimensional fields - something offering the possibility to procedure code better able to catch failures ...
It might have a reason why Niklaus Wirth introduced that in Oberon and other languages also went that way ...
Gruß / Regads
Michael
MODULE DynArray1D;
FROM Storage IMPORT ALLOCATE,DEALLOCATE;
IMPORT STextIO;
IMPORT SWholeIO;
(* Here I assume that INTEGER and SYSTEM.ADDRESS have the same size, *)
(* but this is not essential for this sample *)
CONST MaxV = MAX(INTEGER) DIV SIZE(REAL);
TYPE PVECTOR = POINTER TO ARRAY [0..MaxV-1] OF REAL;
PROCEDURE AddVector( N : CARDINAL;
VAR A : ARRAY OF REAL; (* in *)
VAR B : ARRAY OF REAL; (* in *)
VAR C : ARRAY OF REAL); (* out *)
(* add vector A abd B and return the result in vector C *)
VAR i : CARDINAL;
BEGIN
IF (HIGH(C) < N-1) THEN
(* Some error handling code ... *)
(* but : actually HIGH(C) will be MaxV-1 and NOT N *)
STextIO.WriteLn;
STextIO.WriteString(" HIGH(C) = "); SWholeIO.WriteCard(HIGH(C),1);
STextIO.WriteLn;
STextIO.WriteString(" N = "); SWholeIO.WriteCard(N,1);
STextIO.WriteLn;
STextIO.WriteString(" Error *** HIGH(C) < N-1 (AddVector) ***");
STextIO.WriteLn;
HALT;
END;
FOR i:=0 TO N-1 DO C[i]:= A[i] + B[i]; END;
END AddVector;
VAR A,B,C : PVECTOR;
N,i : CARDINAL;
BEGIN
N := 7; (* suppose N is read in from some source ... *)
ALLOCATE(A,N*SIZE(REAL));
ALLOCATE(B,N*SIZE(REAL));
ALLOCATE(C,N*SIZE(REAL));
FOR i:=0 TO N-1 DO (* some code to initialize A,B ... *)
A^[i] := VAL(REAL,i);
B^[i] := VAL(REAL,2*i);
END;
AddVector(N,A^,B^,C^);
(* Some code to output the result C ... *)
DEALLOCATE(A,N*SIZE(REAL));
DEALLOCATE(B,N*SIZE(REAL));
DEALLOCATE(C,N*SIZE(REAL));
END DynArray1D.
Am 04.04.23 um 18:18 schrieb Fischlin Andreas:
Dear Michael,
Whatever the availability of some of the features are that you envisage to need, it struck me that your sample code seems to suffer from the fact that you squeeze everything into the same program module, while the services you seem to look for
typically should go into a library module.
[MRi: The sample code is only menat to show how my proposual may work. The libraries and programms I have in mind all have several thouthands lines o code and are spread about dozends of modules - shurely nothing to
line out the basics]
By this approach you seem to fully miss out on one of the fundamental features of M2. Notably data abstraction by using e.g. an opaque type exported from a library module. It seems to me before calling for language extensions it would be advisable to first
try to fully exploit the features the language already offers. Perhaps I am wrong with this impression, I just wanted to share it with you as it may possibly help.
Now of course, as Benjamin rightly pointed out, one disadvantage of PIM M2 is that you need "procedures like WriteThis, WriteThat, WriteYetAnotherThat.” for the functionality of Write, which is also true of course for any functionality such as
matrix algebra.
[MRi If you want to have a look on the libraries I actually have in mind see on my (outdated) repository at
https://opensourceprojects.eu/p/modula2 (I need to find a new place to publish the actual versions). ]
Andreas
ETH Zurich
Prof. em. Dr. Andreas Fischlin
IPCC Vice-Chair WGII
Systems Ecology - Institute of Biogeochemistry and Pollutant Dynamics
CHN E 24
Universitaetstrasse 16
8092 Zurich
SWITZERLAND
+41 44 633-6090 phone
+41 44 633-1136 fax
+41 79 595-4050 mobile
Make it as simple as possible, but distrust it!
________________________________________________________________________
Gaius, all,
I have a questions / suggest about a possible extension of GM2.
Would it be possible to have dynamic multidimensional arrays implemented ?
We have multidimensional open array as procedure parameter, but if we come to the main module we already need to know the (maximal) dimension of e.g. a matrix - that does not make a lot of sense in my view. Especially if you have more complex programs where
you do not know upfront the dimensions of the problem you would like to handle.
A small sample code illustrating the approach below - the code should work with AWD Modula, XDS M2 and the P1 compiler - it's the way Oberon addresses the issue (without the "DISPOSE").
Thanks for some feedback
Michael
----------------------------------------------------------------------
MODULE DynArray;
TYPE tVECTOR = ARRAY OF REAL; (* 1-dim open array *)
tMATRIX = ARRAY OF tVECTOR; (* 2-dim open array *)
tPtrVECTOR = POINTER TO tVECTOR; (* pointer to open 1-dim array *)
tPtrMATRIX = POINTER TO tMATRIX; (* pointer to open 2-dim array *)
PROCEDURE MultMatVek( M,N : CARDINAL;
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] *)
VAR i,j : CARDINAL;
s : REAL;
BEGIN
FOR i:=0 TO M-1 DO
s := 0.0;
FOR j:=0 TO N-1 DO s:=s + A[i,j]*B[j]; END;
C[i] := s;
END; (* FOR i *)
END MultMatVek;
VAR A : tPtrMATRIX;
B,C : tPtrVECTOR;
M,N,i,j : CARDINAL;
BEGIN
M := 4;
N := 3; (* suppose M and N are read in from some (external) source ... *)
NEW(A,M,N);
NEW(B,N);
NEW(C,M);
FOR i:=0 TO M-1 DO (* some code to initialize A,B ... *)
FOR j:=0 TO N-1 DO A^[i,j] := VAL(REAL,i+j); END;
END;
FOR i:=0 TO N-1 DO B^[i] := VAL(REAL,i); END;
MultMatVek(M,N,A^,B^,C^);
(* Some code to output the result C ... *)
DISPOSE(A);
DISPOSE(B);
DISPOSE(C);
END DynArray.