[m-rev.] diff: more support for folds over arrays
Julien Fischer
juliensf at csse.unimelb.edu.au
Thu Nov 18 14:27:10 AEDT 2010
Branches: main
Improve support for folds over arrays.
library/array.m:
Add the function array.unsafe_elem/2.
Add a predicate version of array.foldr.
Add the predicate array.foldr2.
Use "unsafe" lookups in the implementations of folds
over arrays - these lookups are safe since the bounds
are checked at the beginning of the fold operation.
Various style fixes.
NEWS:
Announce the new predicates and function.
Julien.
Index: NEWS
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/NEWS,v
retrieving revision 1.543
diff -u -r1.543 NEWS
--- NEWS 13 Nov 2010 16:49:26 -0000 1.543
+++ NEWS 18 Nov 2010 03:21:47 -0000
@@ -43,6 +43,13 @@
accumulators. Modes that provide unique and mostly-unique accumulators
for set fold have also been added.
+* We have made the following changes to the array module of the standard
+ library:
+
+ + The function array.unsafe_elem2/ has been added.
+
+ + The predicates array.foldr/4 and array.foldr2/6 have been added.
+
Changes to the Mercury compiler:
* Support for building and linking against frameworks on Mac OS X has
Index: library/array.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/array.m,v
retrieving revision 1.177
diff -u -r1.177 array.m
--- library/array.m 9 Nov 2010 03:46:32 -0000 1.177
+++ library/array.m 18 Nov 2010 03:21:47 -0000
@@ -258,6 +258,12 @@
%:- mode array.elem(in, array_ui) = out is det.
:- mode array.elem(in, in) = out is det.
+ % As above, but omit the bounds check.
+ %
+:- func array.unsafe_elem(int, array(T)) = T.
+%:- mode array.unsafe_elem(in, array_ui) = out is det.
+:- mode array.unsafe_elem(in, in) = out is det.
+
% Field update for arrays.
% (Array ^ elem(Index) := Value) = array.set(Array, Index, Value).
%
@@ -445,6 +451,36 @@
%:- mode array.foldr(func(in, di) = uo is det, array_ui, di) = uo is det.
:- mode array.foldr(func(in, di) = uo is det, in, di) = uo is det.
+ % array.foldr(P, Array, !Acc) is equivalent to
+ % list.foldr(P, array.to_list(Array), !Acc)
+ % but more efficient.
+ %
+:- pred array.foldr(pred(T1, T2, T2), array(T1), T2, T2).
+:- mode array.foldr(pred(in, in, out) is det, in, in, out) is det.
+:- mode array.foldr(pred(in, mdi, muo) is det, in, mdi, muo) is det.
+:- mode array.foldr(pred(in, di, uo) is det, in, di, uo) is det.
+:- mode array.foldr(pred(in, in, out) is semidet, in, in, out) is semidet.
+:- mode array.foldr(pred(in, mdi, muo) is semidet, in, mdi, muo) is semidet.
+:- mode array.foldr(pred(in, di, uo) is semidet, in, di, uo) is semidet.
+
+ % array.foldr2(P, Array, !Acc1, !Acc2) is equivalent to
+ % list.foldr2(P, array.to_list(Array), !Acc1, !Acc2)
+ % but more efficient.
+ %
+:- pred array.foldr2(pred(T1, T2, T2, T3, T3), array(T1), T2, T2, T3, T3).
+:- mode array.foldr2(pred(in, in, out, in, out) is det, in, in, out, in, out)
+ is det.
+:- mode array.foldr2(pred(in, in, out, mdi, muo) is det, in, in, out, mdi, muo)
+ is det.
+:- mode array.foldr2(pred(in, in, out, di, uo) is det, in, in, out, di, uo)
+ is det.
+:- mode array.foldr2(pred(in, in, out, in, out) is semidet, in,
+ in, out, in, out) is semidet.
+:- mode array.foldr2(pred(in, in, out, mdi, muo) is semidet, in,
+ in, out, mdi, muo) is semidet.
+:- mode array.foldr2(pred(in, in, out, di, uo) is semidet, in,
+ in, out, di, uo) is semidet.
+
% array.random_permutation(A0, A, RS0, RS) permutes the elements in
% A0 given random seed RS0 and returns the permuted array in A
% and the next random seed in RS.
@@ -1526,7 +1562,7 @@
%-----------------------------------------------------------------------------%
array.fetch_items(Array, Low, High, List) :-
- List = foldr_0(func(X, Xs) = [X | Xs], Array, [], Low, High).
+ List = do_foldr_func(func(X, Xs) = [X | Xs], Array, [], Low, High).
%-----------------------------------------------------------------------------%
@@ -1661,6 +1697,9 @@
array.elem(Index, Array) = array.lookup(Array, Index).
+array.unsafe_elem(Index, Array) = Elem :-
+ array.unsafe_lookup(Array, Index, Elem).
+
'elem :='(Index, Array, Value) = array.set(Array, Index, Value).
% ---------------------------------------------------------------------------- %
@@ -1752,87 +1791,145 @@
% ---------------------------------------------------------------------------- %
array.foldl(Fn, A, X) =
- foldl_0(Fn, A, X, array.min(A), array.max(A)).
+ do_foldl_func(Fn, A, X, array.min(A), array.max(A)).
-:- func foldl_0(func(T1, T2) = T2, array(T1), T2, int, int) = T2.
-%:- mode foldl_0(func(in, in) = out is det, array_ui, in, in, in) = out is det.
-:- mode foldl_0(func(in, in) = out is det, in, in, in, in) = out is det.
-%:- mode foldl_0(func(in, di) = uo is det, array_ui, di, in, in) = uo is det.
-:- mode foldl_0(func(in, di) = uo is det, in, di, in, in) = uo is det.
+:- func do_foldl_func(func(T1, T2) = T2, array(T1), T2, int, int) = T2.
+%:- mode do_foldl_func(func(in, in) = out is det, array_ui, in, in, in)
+% = out is det.
+:- mode do_foldl_func(func(in, in) = out is det, in, in, in, in) = out is det.
+%:- mode do_foldl_func(func(in, di) = uo is det, array_ui, di, in, in)
+% = uo is det.
+:- mode do_foldl_func(func(in, di) = uo is det, in, di, in, in) = uo is det.
-foldl_0(Fn, A, X, I, Max) =
+do_foldl_func(Fn, A, X, I, Max) =
( Max < I ->
X
;
- foldl_0(Fn, A, Fn(A ^ elem(I), X), I + 1, Max)
+ do_foldl_func(Fn, A, Fn(A ^ unsafe_elem(I), X), I + 1, Max)
).
% ---------------------------------------------------------------------------- %
-array.foldl(P, A, !X) :-
- array.foldl_0(P, A, array.min(A), array.max(A), !X).
+array.foldl(P, A, !Acc) :-
+ do_foldl_pred(P, A, array.min(A), array.max(A), !Acc).
-:- pred foldl_0(pred(T1, T2, T2), array(T1), int, int, T2, T2).
-:- mode foldl_0(pred(in, in, out) is det, in, in, in, in, out) is det.
-:- mode foldl_0(pred(in, mdi, muo) is det, in, in, in, mdi, muo) is det.
-:- mode foldl_0(pred(in, di, uo) is det, in, in, in, di, uo) is det.
-:- mode foldl_0(pred(in, in, out) is semidet, in, in, in, in, out) is semidet.
-:- mode foldl_0(pred(in, mdi, muo) is semidet, in, in, in, mdi, muo) is semidet.
-:- mode foldl_0(pred(in, di, uo) is semidet, in, in, in, di, uo) is semidet.
+:- pred do_foldl_pred(pred(T1, T2, T2), array(T1), int, int, T2, T2).
+:- mode do_foldl_pred(pred(in, in, out) is det, in, in, in, in, out) is det.
+:- mode do_foldl_pred(pred(in, mdi, muo) is det, in, in, in, mdi, muo) is det.
+:- mode do_foldl_pred(pred(in, di, uo) is det, in, in, in, di, uo) is det.
+:- mode do_foldl_pred(pred(in, in, out) is semidet, in, in, in, in, out)
+ is semidet.
+:- mode do_foldl_pred(pred(in, mdi, muo) is semidet, in, in, in, mdi, muo)
+ is semidet.
+:- mode do_foldl_pred(pred(in, di, uo) is semidet, in, in, in, di, uo)
+ is semidet.
-foldl_0(P, A, I, Max, !X) :-
+do_foldl_pred(P, A, I, Max, !Acc) :-
( Max < I ->
true
;
- P(A ^ elem(I), !X),
- foldl_0(P, A, I+1, Max, !X)
+ P(A ^ unsafe_elem(I), !Acc),
+ do_foldl_pred(P, A, I + 1, Max, !Acc)
).
%-----------------------------------------------------------------------------%
-array.foldl2(P, A, X0, X, Y0, Y) :-
- array.foldl2_0(P, A, array.min(A), array.max(A), X0, X, Y0, Y).
+array.foldl2(P, A, !Acc1, !Acc2) :-
+ do_foldl2(P, array.min(A), array.max(A), A, !Acc1, !Acc2).
-:- pred foldl2_0(pred(T1, T2, T2, T3, T3), array(T1), int, int, T2, T2,
+:- pred do_foldl2(pred(T1, T2, T2, T3, T3), int, int, array(T1), T2, T2,
T3, T3).
-:- mode foldl2_0(pred(in, in, out, in, out) is det, in, in, in, in, out,
+:- mode do_foldl2(pred(in, in, out, in, out) is det, in, in, in, in, out,
in, out) is det.
-:- mode foldl2_0(pred(in, in, out, mdi, muo) is det, in, in, in, in, out,
+:- mode do_foldl2(pred(in, in, out, mdi, muo) is det, in, in, in, in, out,
mdi, muo) is det.
-:- mode foldl2_0(pred(in, in, out, di, uo) is det, in, in, in, in, out,
+:- mode do_foldl2(pred(in, in, out, di, uo) is det, in, in, in, in, out,
di, uo) is det.
-:- mode foldl2_0(pred(in, in, out, in, out) is semidet, in, in, in, in, out,
+:- mode do_foldl2(pred(in, in, out, in, out) is semidet, in, in, in, in, out,
in, out) is semidet.
-:- mode foldl2_0(pred(in, in, out, mdi, muo) is semidet, in, in, in, in, out,
+:- mode do_foldl2(pred(in, in, out, mdi, muo) is semidet, in, in, in, in, out,
mdi, muo) is semidet.
-:- mode foldl2_0(pred(in, in, out, di, uo) is semidet, in, in, in, in, out,
+:- mode do_foldl2(pred(in, in, out, di, uo) is semidet, in, in, in, in, out,
di, uo) is semidet.
-foldl2_0(P, A, I, Max, X0, X, Y0, Y) :-
+do_foldl2(P, I, Max, A, !Acc1, !Acc2) :-
( Max < I ->
- X = X0,
- Y = Y0
+ true
;
- P(A ^ elem(I), X0, X1, Y0, Y1),
- foldl2_0(P, A, I+1, Max, X1, X, Y1, Y)
+ P(A ^ unsafe_elem(I), !Acc1, !Acc2),
+ do_foldl2(P, I + 1, Max, A, !Acc1, !Acc2)
).
%-----------------------------------------------------------------------------%
array.foldr(Fn, A, X) =
- foldr_0(Fn, A, X, array.min(A), array.max(A)).
+ do_foldr_func(Fn, A, X, array.min(A), array.max(A)).
-:- func foldr_0(func(T1, T2) = T2, array(T1), T2, int, int) = T2.
-%:- mode foldr_0(func(in, in) = out is det, array_ui, in, in, in) = out is det.
-:- mode foldr_0(func(in, in) = out is det, in, in, in, in) = out is det.
-%:- mode foldr_0(func(in, di) = uo is det, array_ui, di, in, in) = uo is det.
-:- mode foldr_0(func(in, di) = uo is det, in, di, in, in) = uo is det.
+:- func do_foldr_func(func(T1, T2) = T2, array(T1), T2, int, int) = T2.
+%:- mode do_foldr_func(func(in, in) = out is det, array_ui, in, in, in)
+% = out is det.
+:- mode do_foldr_func(func(in, in) = out is det, in, in, in, in) = out is det.
+%:- mode do_foldr_func(func(in, di) = uo is det, array_ui, di, in, in)
+% = uo is det.
+:- mode do_foldr_func(func(in, di) = uo is det, in, di, in, in) = uo is det.
-foldr_0(Fn, A, X, Min, I) =
+do_foldr_func(Fn, A, X, Min, I) =
( I < Min ->
X
;
- foldr_0(Fn, A, Fn(A ^ elem(I), X), Min, I - 1)
+ do_foldr_func(Fn, A, Fn(A ^ unsafe_elem(I), X), Min, I - 1)
+ ).
+
+%-----------------------------------------------------------------------------%
+
+array.foldr(P, A, !Acc) :-
+ do_foldr_pred(P, array.min(A), array.max(A), A, !Acc).
+
+:- pred do_foldr_pred(pred(T1, T2, T2), int, int, array(T1), T2, T2).
+:- mode do_foldr_pred(pred(in, in, out) is det, in, in, in, in, out) is det.
+:- mode do_foldr_pred(pred(in, mdi, muo) is det, in, in, in, mdi, muo) is det.
+:- mode do_foldr_pred(pred(in, di, uo) is det, in, in, in, di, uo) is det.
+:- mode do_foldr_pred(pred(in, in, out) is semidet, in, in, in, in, out)
+ is semidet.
+:- mode do_foldr_pred(pred(in, mdi, muo) is semidet, in, in, in, mdi, muo)
+ is semidet.
+:- mode do_foldr_pred(pred(in, di, uo) is semidet, in, in, in, di, uo)
+ is semidet.
+
+do_foldr_pred(P, Min, I, A, !Acc) :-
+ ( I < Min ->
+ true
+ ;
+ P(A ^ unsafe_elem(I), !Acc),
+ do_foldr_pred(P, Min, I - 1, A, !Acc)
+ ).
+
+%-----------------------------------------------------------------------------%
+
+array.foldr2(P, A, !Acc1, !Acc2) :-
+ do_foldr2(P, array.min(A), array.max(A), A, !Acc1, !Acc2).
+
+:- pred do_foldr2(pred(T1, T2, T2, T3, T3), int, int, array(T1), T2, T2,
+ T3, T3).
+:- mode do_foldr2(pred(in, in, out, in, out) is det, in, in, in, in, out,
+ in, out) is det.
+:- mode do_foldr2(pred(in, in, out, mdi, muo) is det, in, in, in, in, out,
+ mdi, muo) is det.
+:- mode do_foldr2(pred(in, in, out, di, uo) is det, in, in, in, in, out,
+ di, uo) is det.
+:- mode do_foldr2(pred(in, in, out, in, out) is semidet, in, in, in, in, out,
+ in, out) is semidet.
+:- mode do_foldr2(pred(in, in, out, mdi, muo) is semidet, in, in, in, in, out,
+ mdi, muo) is semidet.
+:- mode do_foldr2(pred(in, in, out, di, uo) is semidet, in, in, in, in, out,
+ di, uo) is semidet.
+
+do_foldr2(P, Min, I, A, !Acc1, !Acc2) :-
+ ( I < Min ->
+ true
+ ;
+ P(A ^ unsafe_elem(I), !Acc1, !Acc2),
+ do_foldr2(P, Min, I - 1, A, !Acc1, !Acc2)
).
%-----------------------------------------------------------------------------%
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list