for review: new predicates in map.m

Zoltan Somogyi zs at cs.mu.OZ.AU
Mon Oct 19 19:24:52 AEST 1998


library/map.m:
	Add some predicates that may be generally useful. Some of them
	are needed in a near-future change to the compiler.

Zoltan.

cvs diff: Diffing .
Index: map.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/map.m,v
retrieving revision 1.65
diff -u -u -r1.65 map.m
--- map.m	1998/08/26 05:45:27	1.65
+++ map.m	1998/10/19 09:22:16
@@ -74,6 +74,11 @@
 						list(V), map(K,V)).
 :- mode map__det_insert_from_corresponding_lists(in, in, in, out) is det.
 
+	% Apply map__det_insert to key - value pairs from the assoc_lists.
+:- pred map__det_insert_from_assoc_list(map(K,V), assoc_list(K, V),
+						map(K,V)).
+:- mode map__det_insert_from_assoc_list(in, in, out) is det.
+
 	% Update the value corresponding to a given key
 	% Fail if the key doesn't already exist.
 :- pred map__update(map(K,V), K, V, map(K,V)).
@@ -90,44 +95,53 @@
 :- mode map__set(di, di, di, uo) is det.
 :- mode map__set(in, in, in, out) is det.
 
-	% Given a map, return a list of all the keys in the map
+	% Given a map, return a list of all the keys in the map.
 :- pred map__keys(map(K, _V), list(K)).
 :- mode map__keys(in, out) is det.
 
-	% Given a map, return a list of all the data values in the map
+	% Given a map, return a list of all the keys in the map,
+	% in sorted order.
+:- pred map__sorted_keys(map(K, _V), list(K)).
+:- mode map__sorted_keys(in, out) is det.
+
+	% Given a map, return a list of all the data values in the map.
 :- pred map__values(map(_K, V), list(V)).
 :- mode map__values(in, out) is det.
 
-	% convert a map to an association list
+	% Convert a map to an association list.
 :- pred map__to_assoc_list(map(K,V), assoc_list(K,V)).
 :- mode map__to_assoc_list(in, out) is det.
 
-	% convert an association list to a map
+	% Convert a map to an association list which is sorted on the keys.
+:- pred map__to_sorted_assoc_list(map(K,V), assoc_list(K,V)).
+:- mode map__to_sorted_assoc_list(in, out) is det.
+
+	% Convert an association list to a map.
 :- pred map__from_assoc_list(assoc_list(K,V), map(K,V)).
 :- mode map__from_assoc_list(in, out) is det.
 
-	% convert a sorted association list to a map
+	% Convert a sorted association list to a map.
 :- pred map__from_sorted_assoc_list(assoc_list(K,V), map(K,V)).
 :- mode map__from_sorted_assoc_list(in, out) is det.
 
-	% delete a key-value pair from a map
-	% if the key is not present, leave the map unchanged
+	% Delete a key-value pair from a map.
+	% If the key is not present, leave the map unchanged.
 :- pred map__delete(map(K,V), K, map(K,V)).
 :- mode map__delete(di, in, uo) is det.
 :- mode map__delete(in, in, out) is det.
 
-	% apply map__delete/3 to a list of keys
+	% Apply map__delete/3 to a list of keys.
 :- pred map__delete_list(map(K,V), list(K), map(K,V)).
 :- mode map__delete_list(di, in, uo) is det.
 :- mode map__delete_list(in, in, out) is det.
 
-	% delete a key-value pair from a map and return the value.
-	% fail if the key is not present
+	% Delete a key-value pair from a map and return the value.
+	% Fail if the key is not present.
 :- pred map__remove(map(K,V), K, V, map(K,V)).
 :- mode map__remove(in, in, out, out) is semidet.
 
-	% delete a key-value pair from a map and return the value.
-	% abort if the key is not present
+	% Delete a key-value pair from a map and return the value.
+	% Abort if the key is not present.
 :- pred map__det_remove(map(K,V), K, V, map(K,V)).
 :- mode map__det_remove(in, in, out, out) is det.
 
@@ -188,6 +202,38 @@
 :- mode map__map_values(pred(in, in, out) is det, in, out) is det.
 :- mode map__map_values(pred(in, in, out) is semidet, in, out) is semidet.
 
+	% Given two maps M1 and M2, create a third map M3 that has only the
+	% keys that occur in both M1 and M2. For keys that occur in both M1
+	% and M2, compute the value in the final map by applying the supplied
+	% predicate to the values associated with the key in M1 and M2.
+	% Fail if and only if this predicate fails on the values associated
+	% with some common key.
+:- pred map__intersect(pred(V, V, V), map(K, V), map(K, V), map(K, V)).
+:- mode map__intersect(pred(in, in, out) is semidet, in, in, out) is semidet.
+:- mode map__intersect(pred(in, in, out) is det, in, in, out) is det.
+
+	% Calls map__intersect. Abort (with the last argument as the message)
+	% if map__intersect fails.
+:- pred map__det_intersect(pred(V, V, V), map(K, V), map(K, V), map(K, V),
+	string).
+:- mode map__det_intersect(pred(in, in, out) is semidet, in, in, out, in)
+	is det.
+
+	% Given two maps M1 and M2, create a third map M3 that all the keys
+	% that occur in either M1 and M2. For keys that occur in both M1
+	% and M2, compute the value in the final map by applying the supplied
+	% predicate to the values associated with the key in M1 and M2.
+	% Fail if and only if this predicate fails on the values associated
+	% with some common key.
+:- pred map__union(pred(V, V, V), map(K, V), map(K, V), map(K, V)).
+:- mode map__union(pred(in, in, out) is semidet, in, in, out) is semidet.
+:- mode map__union(pred(in, in, out) is det, in, in, out) is det.
+
+	% Calls map__union. Abort (with the last argument as the message)
+	% if map__intersect fails.
+:- pred map__det_union(pred(V, V, V), map(K, V), map(K, V), map(K, V), string).
+:- mode map__det_union(pred(in, in, out) is semidet, in, in, out, in) is det.
+
 %-----------------------------------------------------------------------------%
 
 :- import_module tree234.
@@ -276,6 +322,11 @@
 		error("map__det_insert_from_corresponding_lists - lists do not correspond")
 	).
 
+map__det_insert_from_assoc_list(Map, [], Map).
+map__det_insert_from_assoc_list(Map0, [K - V | KVs], Map) :-
+	map__det_insert(Map0, K, V, Map1),
+	map__det_insert_from_assoc_list(Map1, KVs, Map).
+
 map__update(Map0, K, V, Map) :-
 	tree234__update(Map0, K, V, Map).
 
@@ -292,12 +343,20 @@
 map__keys(Map, KeyList) :-
 	tree234__keys(Map, KeyList).
 
+map__sorted_keys(Map, KeyList) :-
+	% Guaranteed to yield sorted lists.
+	tree234__keys(Map, KeyList).
+
 map__values(Map, KeyList) :-
 	tree234__values(Map, KeyList).
 
 map__to_assoc_list(M, L) :-
 	tree234__tree234_to_assoc_list(M, L).
 
+map__to_sorted_assoc_list(M, L) :-
+	% Guaranteed to yield sorted lists.
+	tree234__tree234_to_assoc_list(M, L).
+
 map__from_assoc_list(L, M) :-
 	tree234__assoc_list_to_tree234(L, M).
 
@@ -423,6 +482,120 @@
 
 map__map_values(Pred, Map0, Map) :-
 	tree234__map_values(Pred, Map0, Map).
+
+%-----------------------------------------------------------------------------%
+
+map__intersect(CommonPred, Map1, Map2, Common) :-
+	map__to_sorted_assoc_list(Map1, AssocList1),
+	map__to_sorted_assoc_list(Map2, AssocList2),
+	map__init(Common0),
+	map__intersect_2(AssocList1, AssocList2, CommonPred, Common0, Common).
+
+:- pred map__intersect_2(assoc_list(K, V), assoc_list(K, V), pred(V, V, V),
+	map(K, V), map(K, V)).
+:- mode map__intersect_2(in, in, pred(in, in, out) is semidet, in, out)
+	is semidet.
+:- mode map__intersect_2(in, in, pred(in, in, out) is det, in, out)
+	is det.
+
+map__intersect_2(AssocList1, AssocList2, CommonPred, Common0, Common) :-
+	(
+		AssocList1 = [],
+		AssocList2 = [],
+		Common = Common0
+	;
+		AssocList1 = [_ | _],
+		AssocList2 = [],
+		Common = Common0
+	;
+		AssocList1 = [],
+		AssocList2 = [_ | _],
+		Common = Common0
+	;
+		AssocList1 = [Key1 - Value1 | AssocTail1],
+		AssocList2 = [Key2 - Value2 | AssocTail2],
+		compare(R, Key1, Key2),
+		(
+			R = (=),
+			call(CommonPred, Value1, Value2, Value),
+			map__det_insert(Common0, Key1, Value, Common1),
+			map__intersect_2(AssocTail1, AssocList2, CommonPred,
+				Common1, Common)
+		;
+			R = (<),
+			map__intersect_2(AssocTail1, AssocList2, CommonPred,
+				Common0, Common)
+		;
+			R = (>),
+			map__intersect_2(AssocList1, AssocTail2, CommonPred,
+				Common0, Common)
+		)
+	).
+
+map__det_intersect(CommonPred, Map1, Map2, Common, Msg) :-
+	( map__intersect(CommonPred, Map1, Map2, CommonPrime) ->
+		Common = CommonPrime
+	;
+		error(Msg)
+	).
+
+%-----------------------------------------------------------------------------%
+
+map__union(CommonPred, Map1, Map2, Common) :-
+	map__to_sorted_assoc_list(Map1, AssocList1),
+	map__to_sorted_assoc_list(Map2, AssocList2),
+	map__init(Common0),
+	map__union_2(AssocList1, AssocList2, CommonPred, Common0, Common).
+
+:- pred map__union_2(assoc_list(K, V), assoc_list(K, V), pred(V, V, V),
+	map(K, V), map(K, V)).
+:- mode map__union_2(in, in, pred(in, in, out) is semidet, in, out)
+	is semidet.
+:- mode map__union_2(in, in, pred(in, in, out) is det, in, out)
+	is det.
+
+map__union_2(AssocList1, AssocList2, CommonPred, Common0, Common) :-
+	(
+		AssocList1 = [],
+		AssocList2 = [],
+		Common = Common0
+	;
+		AssocList1 = [_ | _],
+		AssocList2 = [],
+		map__det_insert_from_assoc_list(Common0, AssocList1, Common)
+	;
+		AssocList1 = [],
+		AssocList2 = [_ | _],
+		map__det_insert_from_assoc_list(Common0, AssocList2, Common)
+	;
+		AssocList1 = [Key1 - Value1 | AssocTail1],
+		AssocList2 = [Key2 - Value2 | AssocTail2],
+		compare(R, Key1, Key2),
+		(
+			R = (=),
+			call(CommonPred, Value1, Value2, Value),
+			map__det_insert(Common0, Key1, Value, Common1),
+			map__union_2(AssocTail1, AssocList2, CommonPred,
+				Common1, Common)
+		;
+			R = (<),
+			map__det_insert(Common0, Key1, Value1, Common1),
+			map__union_2(AssocTail1, AssocList2, CommonPred,
+				Common1, Common)
+		;
+			R = (>),
+			map__det_insert(Common0, Key2, Value2, Common1),
+			map__union_2(AssocList1, AssocTail2, CommonPred,
+				Common1, Common)
+		)
+	).
+
+map__det_union(CommonPred, Map1, Map2, Union, Msg) :-
+	( map__union(CommonPred, Map1, Map2, UnionPrime) ->
+		Union = UnionPrime
+	;
+		error(Msg)
+	).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%



More information about the developers mailing list