[m-rev.] New library module: table.m

Ralph Becket rafe at cs.mu.OZ.AU
Tue Jan 21 18:26:01 AEDT 2003


Fergus Henderson, Tuesday, 21 January 2003:
> On 21-Jan-2003, Ralph Becket <rafe at cs.mu.OZ.AU> wrote:
> > Added a new library module, table.m, implementing 2d rectangular arrays.
> 
> Hmm.  Would it be better to name this `array2d', or `matrix',
> rather than `table'?
> 
> I think I prefer the name `array2d'.

I thought about this one and ended up with `table'; `matrix' suggests
a numerical array to me.  I'm happy to change if there's a majority
preference.

> > tests/hard_coded/test_table.m:
> > tests/hard_coded/test_table.exp:
> > tests/hard_coded/Mmakefile:
> > 	Test case added.
> 
> The test case should IMHO also test that the implementation does bounds
> checking.

Done.

> > Index: library/table.m
> > +    % table([[X11, ..., X1N], ..., [XM1, ..., XMN]]) constructs a table
> > +    % of size M * N.
> ...
> > +    % new(M, N, X) = table([[X11, ..., X1N], ..., [XM1, ..., XMN]])
> > +    % where each XIJ = X.
> ...
> > +    % table([[X11, ..., X1N], ..., [XM1, ..., XMN]]) ^ elem(I, J) = XIJ
> > +    %
> > +    % An exception is thrown unless 0 =< I < M, 0 =< J < N.
> 
> Do table indexes start at zero, or at 1?
> 
> The documentation for `elem' is contradictory on this point.
> The use of "X11, ..., X1N" in the documentation of `table',
> `new', and `elem' strongly suggests that indexes start at 1.
> And the definition of elem(I, J) = XIJ confirms it.
> But then the bit about when exceptions get thrown contradicts this.

You're right.  Indices start at zero; I've changed the documentation.

> > +    % table(Rows, Cols, Array)
> > +    %
> > +:- type table(T) ---> table(int, int, array(T)).
> 
> You should document here whether the table is stored in
> row-major or column-major order.

Done.

> > +table(Xss @ [Xs | _]) = T :-
> > +
> > +    M = length(Xss),
> > +    N = length(Xs),
> > +    T = table(M, N, A @ array(condense(Xss))),
> > +
> > +    ( size(A) \= M * N =>
> > +        error("table.table/1: non-rectangular list of lists") ).
> 
> The error condition might not get checked if this code is compiled
> with --no-fully-strict, which would contravene the documentation for
> this function.  So either the code should be rewritten so that it
> only binds T in the case when size(A) = M * N, or you should add a comment
> here and also in the Mmakefile, where it passes `--strict-sequential',
> saying that this code relies on it.  I recommend the former.

Fixed.

Here's the interdiff:

diff -u library/table.m library/table.m
--- library/table.m	21 Jan 2003 03:34:56 -0000
+++ library/table.m	21 Jan 2003 07:21:15 -0000
@@ -18,6 +18,10 @@
 
 
 
+    % A table is a two-dimensional array stored in row-major order
+    % (that is, the elements of the first row in left-to-right
+    % order, followed by the elements of the second row and so forth.)
+    %
 :- type table(T).
 
 :- inst table ---> table(ground, ground, array).
@@ -32,7 +36,7 @@
 
 
     % table([[X11, ..., X1N], ..., [XM1, ..., XMN]]) constructs a table
-    % of size M * N.
+    % of size M * N, with the special case that bounds(table([]), 0, 0).
     %
     % An exception is thrown if the sublists are not all the same length.
     %
@@ -45,7 +49,9 @@
 :- func new(int, int, T ) = table(T).
 :- mode new(in,  in,  in) = table_uo is det.
 
-    % table([[X11, ..., X1N], ..., [XM1, ..., XMN]]) ^ elem(I, J) = XIJ
+    % table([[X11, ..., X1N], ..., [XM1, ..., XMN]]) ^ elem(I, J) = X
+    % where X is the J+1th element of the I+1th row (that is, indices
+    % start from zero.)
     %
     % An exception is thrown unless 0 =< I < M, 0 =< J < N.
     %
@@ -60,8 +66,9 @@
 :- mode table_ui ^ unsafe_elem(in,  in ) = out is det.
 :- mode in       ^ unsafe_elem(in,  in ) = out is det.
 
-    % ( table([[X11, ..., X1N], ..., [XM1, ..., XMN]]) ^ elem(I, J) := XIJ ) =
-    %     table([[X11, ..., X1N], ..., [..., XIJ, ...], ..., [XM1, ..., XMN]])
+    % ( T0 ^ elem(I, J) := X ) = T
+    % where T ^ elem(II, JJ) = X                 if I = II, J = JJ
+    % and   T ^ elem(II, JJ) = T0 ^ elem(II, JJ) otherwise.
     %
     % An exception is thrown unless 0 =< I < M, 0 =< J < N.
     %
@@ -111,21 +118,23 @@
 
 table(      []      ) = table(0, 0, make_empty_array).
 
-table(Xss @ [Xs | _]) = T :-
-
-    M = length(Xss),
-    N = length(Xs),
-    T = table(M, N, A @ array(condense(Xss))),
-
-    ( size(A) \= M * N =>
-        error("table.table/1: non-rectangular list of lists") ).
+table(Xss @ [Xs | _]) =
+    ( if 
+        M = length(Xss),
+        N = length(Xs),
+        all [Ys] ( member(Ys, Xss) => length(Ys) = N ),
+      then
+        table(M, N, array(condense(Xss)))
+      else
+        func_error("table.table/1: non-rectangular list of lists")
+    ).
 
 %-----------------------------------------------------------------------------%
 
 new(M, N, X) =
     ( if   M >= 0, N >= 0
       then table(M, N, array.init(M * N, X))
-      else func_error("table.new: dimensions must be non-negative")
+      else func_error("table.new: bounds must be non-negative")
     ).
 
 %-----------------------------------------------------------------------------%
diff -u tests/hard_coded/test_table.m tests/hard_coded/test_table.m
--- tests/hard_coded/test_table.m	21 Jan 2003 03:51:22 -0000
+++ tests/hard_coded/test_table.m	21 Jan 2003 07:01:27 -0000
@@ -14,14 +14,14 @@
 
 
 
-:- pred main(io::di, io::uo) is det.
+:- pred main(io::di, io::uo) is cc_multi.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
 :- implementation.
 
-:- import_module int, list, string, table, pprint.
+:- import_module int, list, string, table, pprint, exception.
 
 %-----------------------------------------------------------------------------%
 
@@ -54,6 +54,22 @@
 
     Zeroes = table.new(3, 3, 0),
     write_table("Zeroes", Zeroes, !IO),
+
+    try((pred(X::out) is det :- X = Empty  ^ elem( 0,  0)), Ea),
+    try((pred(X::out) is det :- X = Zeroes ^ elem(-1,  0)), Eb),
+    try((pred(X::out) is det :- X = Zeroes ^ elem( 0, -1)), Ec),
+    try((pred(X::out) is det :- X = Zeroes ^ elem(-1, -1)), Ed),
+    try((pred(X::out) is det :- X = Zeroes ^ elem( 3,  0)), Ee),
+    try((pred(X::out) is det :- X = Zeroes ^ elem( 0,  3)), Ef),
+    try((pred(X::out) is det :- X = Zeroes ^ elem( 3,  3)), Eg),
+
+    io.print(Ea, !IO), io.nl(!IO),
+    io.print(Eb, !IO), io.nl(!IO),
+    io.print(Ec, !IO), io.nl(!IO),
+    io.print(Ed, !IO), io.nl(!IO),
+    io.print(Ee, !IO), io.nl(!IO),
+    io.print(Ef, !IO), io.nl(!IO),
+    io.print(Eg, !IO), io.nl(!IO),
 
     true.
 

Cheers,
	Ralph
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list