[m-dev.] for review: add a new pred to array.m

Thomas Charles Conway conway at hydra.cs.mu.oz.au
Wed Mar 31 10:21:21 AEST 1999


On Tue, Mar 30, 1999 at 05:09:09PM EST, Fergus Henderson wrote:
> On 30-Mar-1999, Thomas Charles Conway <conway at hydra.cs.mu.oz.au> wrote:
> How about just
> 
> 	* We've added some new predicates to the Mercury standard library:
> 		bag__count_value/3,
> 		array__map/3.
> 
> ?

Done.

> If you want short names for type variables, I much prefer T1, T2, ...
> rather than T, U, ...

Done.

> 
> Any particular reason why this is a predicate, rather than a function?
> The old rationale for using predicates was for debugging with Prolog, 
> but that doesn't apply now.
> 

Well, it's more consistent with the rest of the array module.

> > +	% The current implementation of array__map converts to a list,
> > +	% invokes list__map, then converts back to an array representation.
> > +	% It would be nicer to be able to do the map on each element
> > +	% maintaining the same array skeleton. Unfortunately this is
> > +	% tricky since the intermediate arrays have some elements of
> > +	% one type, and some of the other.
> 
> Yes, that would be tricky -- particularly for the accurate garbage collector
> and the debugger.  I don't think it would be worthwhile to try to make them
> somehow cope with mixed arrays like this.

I had in mind something more like the array partitioning scheme you
and I once talked about. eg
	% :- type partition(T) more-or-less-== array(T)
	%  partition(Whole, Ind, Part1, Part2)
	% [Pmin, Ind-1] -> Part1
	% [Ind, Pmax] -> Part2
	% where Pmin and Pmax are the minimum and maximum indices of
	% the whole partition.
	:- pred partition(partition(T), int, partition(T), partition(T)).
	:- mode partition(array_di, in, array_uo, array_uo) is det.

which splits the array into two parts at the given index. Now, you
could make a version of array__map which only works on signleton
partitions then use a combine predicate:
	:- pred combine(parition(T), partition(T), partition(T)).
	:- mode combine(array_di, array_di, array_uo) is det.
(and make combine abort if you try to combine non-adjacent partitions).

Now map can be written something like:
	
array__map(Closure, OldArray, NewArray) :-
	array__size(OldArray, Size),
	array__to_partition(OldArray, Part0),
	partition(Part0, 0, DonePart0, RemainingPart), % DonePart0 is empty
		% It's safe to coerce the type since there
		% are no elements
	coerce(DonePart0, DonePart1),
	array__map2(0, Size, Closure, RemainingPart, DonePart1, DonePart),
	array__from_partition(DonePart, NewArray).

array__map2(Ind, Size, Closure, RemainingPart0, DonePart0, DonePart) :-
	( Ind >= Size ->
		DonePart = DonePart0
	;
		partition(RemainingPart0, Ind + 1, PartToDo, RemainingPart),
		map_singleton_partition(Closure, PartToDo, PartDone),
		combine(DonePart0, PartDone, DonePart1),
		array__map2(Ind + 1, Size, Closure, RemainingPart,
			DonePart1, DonePart)
	).

Now, given an appropriate C representation for partitions, it shouldn't
be too hard to convince accurate GC to do the right job.

> 
> So a zero-copy implementation is tricky, in general.
> However, it's certainly quite possible to do better than your two-copy
> implementation.  A one-copy implementation should be straight-forward, no?
> 

Yes, you're right.
See the revised diff.

> 
> If you want to get tricky, you could special-case this for the case
> where the two types are the same, using a dynamic type test:
> 

I haven't bothered with this.

Here's a revised diff.

-- 
Thomas Conway <conway at cs.mu.oz.au> )O+
To a killer whale, otters are like hairy popcorn -- Paul Dayton

cvs diff: Diffing .
Index: NEWS
===================================================================
RCS file: /home/staff/zs/imp/mercury/NEWS,v
retrieving revision 1.141
diff -u -r1.141 NEWS
--- NEWS	1999/03/30 05:45:17	1.141
+++ NEWS	1999/03/30 23:57:58
@@ -39,7 +39,8 @@
 Changes to the Mercury standard library:
 ****************************************
 
-* We've added a new predicate to the Mercury standard library:
+* We've added some new predicates to the Mercury standard library:
+	array__map/3,
 	bag__count_value/3.
 
 * The following predicates have been replaced by functions with
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing bytecode/test
cvs diff: Diffing compiler
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/aditi
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/exceptions
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing library
Index: library/array.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/array.m,v
retrieving revision 1.52
diff -u -r1.52 array.m
--- array.m	1999/03/22 08:08:40	1.52
+++ array.m	1999/03/30 23:50:27
@@ -209,6 +209,11 @@
 :- mode array__bsearch(array_ui, in, pred(in, in, out) is det, out) is det.
 :- mode array__bsearch(in, in, pred(in, in, out) is det, out) is det.
 
+	% array__map(Closure, OldArray, NewArray) applys `Closure' to
+	% each of the elements of `OldArray' to create `NewArray'.
+:- pred array__map(pred(T1, T2), array(T1), array(T2)).
+:- mode array__map(pred(in, out) is det, array_di, array_uo) is det.
+
 %-----------------------------------------------------------------------------%
 :- implementation.
 
@@ -719,6 +724,34 @@
 		    array__bsearch_2(Array, Lo, Mid1, El, Compare, Result)
 	        )
 	    )
+	).
+
+%-----------------------------------------------------------------------------%
+
+array__map(Closure, OldArray, NewArray) :-
+	( array__semidet_lookup(OldArray, 0, Elem0) ->
+		array__size(OldArray, Size),
+		call(Closure, Elem0, Elem),
+		array__init(Size, Elem, NewArray0),
+		array__map_2(0, Size, Closure, OldArray,
+		NewArray0, NewArray)
+	;
+		array__make_empty_array(NewArray)
+	).
+
+:- pred array__map_2(int, int, pred(T1, T2), array(T1), array(T2), array(T2)).
+:- mode array__map_2(in, in, pred(in, out) is det, in, array_di, array_uo)
+		is det.
+
+array__map_2(N, Size, Closure, OldArray, NewArray0, NewArray) :-
+	( N >= Size ->
+		NewArray = NewArray0
+	;
+		array__lookup(OldArray, N, OldElem),
+		Closure(OldElem, NewElem),
+		array__set(NewArray0, N, NewElem, NewArray1),
+		array__map_2(N + 1, Size, Closure, OldArray,
+		NewArray1, NewArray)
 	).
 
 %-----------------------------------------------------------------------------%
cvs diff: Diffing lp_solve
cvs diff: Diffing lp_solve/lp_examples
cvs diff: Diffing profiler
cvs diff: Diffing readline
cvs diff: Diffing readline/doc
cvs diff: Diffing readline/examples
cvs diff: Diffing readline/shlib
cvs diff: Diffing readline/support
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing scripts
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing trial
cvs diff: Diffing util



More information about the developers mailing list