[m-dev.] For review: updates to library/rbtree.m

Warwick Harvey wh at icparc.ic.ac.uk
Mon May 15 21:44:39 AEST 2000


Fergus wrote:
> On 12-May-2000, Warwick Harvey <wh at icparc.ic.ac.uk> wrote: 
> > As per some private mail exchanged with Fergus, I've been looking at the 
> > rbtree module, as an alternative to tree234 as the underlying 
> > implementation of map. It was missing a few things that tree234 has, 
> > and as such was not plug-in compatible. These changes fix that by 
> > bringing rbtree "up to speed", so to speak. 
> 
> That change looks good, Warwick.

Unfortunately, it didn't boot check (I should have verified that the
version I checked out worked first, so I'd know whether the problem was
with the rbtree module or not...  Doing that now).  Obviously I'll post
any patches needed to fix rbtree before I commit anything.

> I'd prefer the version with unique modes. 

Yup, my only concern with that was the code duplication, but, as
happens, lying in bed that night I figured out how to avoid it.  :-) 
Here's a diff between the old unique modes version and the new one, as
well as a full diff relative to the repository.

Probably some of the ( -> ; -> ; ) constructs in this module should be
converted to switches.  Perhaps `yes' and `no' insts could be added to
bool.m as well --- though maybe they wouldn't be used often enough to
warrant it (I couldn't find any other references to `bound(yes)' or
`bound(no)' in the compiler).

Cheers,
Warwick
-------------- next part --------------
--- rbtree.m.unique	Mon May 15 11:29:06 2000
+++ rbtree.m	Mon May 15 12:38:18 2000
@@ -170,7 +170,7 @@
 
 :- implementation.
 
-:- import_module int, require, std_util.
+:- import_module bool, int, require, std_util.
 
 
 :- type rbtree(K,V)	 --->	empty
@@ -750,72 +750,17 @@
 
 %-----------------------------------------------------------------------------%
 
-rbtree__delete(empty, _K, empty).
-rbtree__delete(red(K0, V0, L, R), K, Tree) :-
-	compare(Result, K, K0),
-	(	
-		Result = (=)
-	->
-		(
-			rbtree__remove_largest(L, NewK, NewV, NewL)
-		->
-			Tree = red(NewK, NewV, NewL, R)
-		;
-			% L must be empty
-			(
-				rbtree__remove_smallest(R, NewK, NewV, NewR)
-			->
-				Tree = red(NewK, NewV, empty, NewR)
-			;
-				% R must be empty
-				Tree = empty
-			)
-		)
-	;
-
-		Result = (<)
-	->
-		rbtree__delete(L, K, NewL),
-		Tree = red(K0, V0, NewL, R)
-	;
-		rbtree__delete(R, K, NewR),
-		Tree = red(K0, V0, L, NewR)
-	).
-rbtree__delete(black(K0, V0, L, R), K, Tree) :-
-	compare(Result, K, K0),
-	(	
-		Result = (=)
-	->
-		(
-			rbtree__remove_largest(L, NewK, NewV, NewL)
-		->
-			Tree = black(NewK, NewV, NewL, R)
-		;
-			% L must be empty
-			(
-				rbtree__remove_smallest(R, NewK, NewV, NewR)
-			->
-				Tree = black(NewK, NewV, empty, NewR)
-			;
-				% R must be empty
-				Tree = empty
-			)
-		)
-	;
-
-		Result = (<)
-	->
-		rbtree__delete(L, K, NewL),
-		Tree = black(K0, V0, NewL, R)
-	;
-		rbtree__delete(R, K, NewR),
-		Tree = black(K0, V0, L, NewR)
-	).
-
-%-----------------------------------------------------------------------------%
+rbtree__delete(Tree0, K, Tree) :-
+	rbtree__delete_2(Tree0, K, no, _, Tree).
 
-% rbtree_remove:
-%	Search down the tree, looking for the node to remove.  O(log N)
+% rbtree__delete_2(Tree0, Key, MustRemove, MaybeValue, Tree):
+%	Search the tree Tree0, looking for a node with key Key to delete.
+%	If MustRemove is `yes' and we don't find the key, fail.
+%	If we find the key, return it in MaybeValue and delete the node.
+%	Tree is the resulting tree, whether a node was removed or not.
+%
+% Deletion algorithm:
+%	Search down the tree, looking for the node to delete.  O(log N)
 %	When we find it, there are 4 possible conditions ->
 %		* Leaf node
 %		    Remove node  O(1)
@@ -823,14 +768,19 @@
 %		    Move maximum key of Left subtree to current node. O(log N)
 %		* Right subtree of node to be deleted exists
 %		    Move minimum key of Right subtree to current node. O(log N)
-%		* Both of node to be deleted left and right subtree exist
+%		* Both left and right subtrees of node to be deleted exist
 %		    Move maximum key of Left subtree to current node. O(log N)
 %
 %	Algorithm O(log N).
 
-rbtree__remove(empty, _K, _V, _Tree) :-
-	fail.
-rbtree__remove(red(K0, V0, L, R), K, V, Tree) :-
+:- pred rbtree__delete_2(rbtree(K, V), K, bool, maybe(V), rbtree(K, V)).
+:- mode rbtree__delete_2(di, in, in, uo, uo) is semidet.
+:- mode rbtree__delete_2(di, in, in(bound(no)), uo, uo) is det.
+:- mode rbtree__delete_2(in, in, in, out, out) is semidet.
+:- mode rbtree__delete_2(in, in, in(bound(no)), out, out) is det.
+
+rbtree__delete_2(empty, _K, no, no, empty).
+rbtree__delete_2(red(K0, V0, L, R), K, MustRemove, MaybeV, Tree) :-
 	compare(Result, K, K0),
 	(	
 		Result = (=)
@@ -850,18 +800,18 @@
 				Tree = empty
 			)
 		),
-		V = V0
+		MaybeV = yes(V0)
 	;
 
 		Result = (<)
 	->
-		rbtree__remove(L, K, V, NewL),
+		rbtree__delete_2(L, K, MustRemove, MaybeV, NewL),
 		Tree = red(K0, V0, NewL, R)
 	;
-		rbtree__remove(R, K, V, NewR),
+		rbtree__delete_2(R, K, MustRemove, MaybeV, NewR),
 		Tree = red(K0, V0, L, NewR)
 	).
-rbtree__remove(black(K0, V0, L, R), K, V, Tree) :-
+rbtree__delete_2(black(K0, V0, L, R), K, MustRemove, MaybeV, Tree) :-
 	compare(Result, K, K0),
 	(	
 		Result = (=)
@@ -881,17 +831,22 @@
 				Tree = empty
 			)
 		),
-		V = V0
+		MaybeV = yes(V0)
 	;
 
 		Result = (<)
 	->
-		rbtree__remove(L, K, V, NewL),
+		rbtree__delete_2(L, K, MustRemove, MaybeV, NewL),
 		Tree = black(K0, V0, NewL, R)
 	;
-		rbtree__remove(R, K, V, NewR),
+		rbtree__delete_2(R, K, MustRemove, MaybeV, NewR),
 		Tree = black(K0, V0, L, NewR)
 	).
+
+%-----------------------------------------------------------------------------%
+
+rbtree__remove(Tree0, K, V, Tree) :-
+	rbtree__delete_2(Tree0, K, yes, yes(V), Tree).
 
 rbtree__remove(Tree0, K, Tree) :-
 	rbtree__remove(Tree0, K, _, Tree).
-------------- next part --------------
Index: rbtree.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/rbtree.m,v
retrieving revision 1.12
diff -u -r1.12 rbtree.m
--- rbtree.m	2000/05/12 17:28:44	1.12
+++ rbtree.m	2000/05/15 11:40:08
@@ -44,8 +44,12 @@
 
 	% Initialise the data structure.
 :- pred rbtree__init(rbtree(K, V)).
-:- mode rbtree__init(out) is det.
+:- mode rbtree__init(uo) is det.
 
+	% Check whether a tree is empty.
+:- pred rbtree__is_empty(rbtree(K, V)).
+:- mode rbtree__is_empty(in) is semidet.
+
 	% Inserts a new key-value pair into the tree.  Fails if key 
 	% already in the tree.
 :- pred rbtree__insert(rbtree(K, V), K, V, rbtree(K, V)).
@@ -59,12 +63,16 @@
 	% Sets a value irregardless of whether key exists or not.  Never
 	% fails.
 :- pred rbtree__set(rbtree(K, V), K, V, rbtree(K, V)).
+:- mode rbtree__set(di, di, di, uo) is det.
 :- mode rbtree__set(in, in, in, out) is det.
 
 	% Insert a duplicate key into the tree.  Never fails.
 :- pred rbtree__insert_duplicate(rbtree(K, V), K, V, rbtree(K, V)).
 :- mode rbtree__insert_duplicate(in, in, in, out) is det.
 
+:- pred rbtree__member(rbtree(K, V), K, V).
+:- mode rbtree__member(in, out, out) is nondet.
+
 	% Search for a key-value pair using the key.  Fails if key doesn't
 	% exist.
 :- pred rbtree__search(rbtree(K, V), K, V).
@@ -102,13 +110,33 @@
 	% Delete the key value pair associated with a key.  Does nothing
 	% if the key doesn't exist.
 :- pred rbtree__delete(rbtree(K, V), K, rbtree(K, V)).
+:- mode rbtree__delete(di, in, uo) is det.
 :- mode rbtree__delete(in, in, out) is det.
 
 	% Remove the key value pair associated with a key.  Fails
 	% if the key doesn't exist.
+:- pred rbtree__remove(rbtree(K, V), K, V, rbtree(K, V)).
+:- mode rbtree__remove(di, in, uo, uo) is semidet.
+:- mode rbtree__remove(in, in, out, out) is semidet.
+
+	% Same as above, except this version does not return the value
+	% corresponding to the key.  Its use is deprecated, but it is
+	% kept for compatibility with older versions of this library.
 :- pred rbtree__remove(rbtree(K, V), K, rbtree(K, V)).
 :- mode rbtree__remove(in, in, out) is semidet.
 
+	% Deletes the node with the minimum K from the tree, and returns
+	% the key and value fields.
+:- pred rbtree__remove_smallest(rbtree(K, V), K, V, rbtree(K, V)).
+:- mode rbtree__remove_smallest(di, uo, uo, uo) is semidet.
+:- mode rbtree__remove_smallest(in, out, out, out) is semidet.
+
+	% Deletes the node with the maximum K from the tree, and returns
+	% the key and value fields.
+:- pred rbtree__remove_largest(rbtree(K, V), K, V, rbtree(K, V)).
+:- mode rbtree__remove_largest(di, uo, uo, uo) is semidet.
+:- mode rbtree__remove_largest(in, out, out, out) is semidet.
+
 	% Returns an in-order list of all the keys in the rbtree.
 :- pred rbtree__keys(rbtree(K, V), list(K)).
 :- mode rbtree__keys(in, out) is det.
@@ -128,11 +156,21 @@
 :- pred rbtree__rbtree_to_assoc_list(rbtree(K, V), assoc_list(K, V)).
 :- mode rbtree__rbtree_to_assoc_list(in, out) is det.
 
+:- pred rbtree__foldl(pred(K, V, T, T), rbtree(K, V), T, T).
+:- mode rbtree__foldl(pred(in, in, in, out) is det, in, in, out) is det.
+:- mode rbtree__foldl(pred(in, in, in, out) is semidet, in, in, out)
+		is semidet.
+:- mode rbtree__foldl(pred(in, in, di, uo) is det, in, di, uo) is det.
+
+:- pred rbtree__map_values(pred(K, V, W), rbtree(K, V), rbtree(K, W)).
+:- mode rbtree__map_values(pred(in, in, out) is det, in, out) is det.
+:- mode rbtree__map_values(pred(in, in, out) is semidet, in, out) is semidet.
+
 %-----------------------------------------------------------------------------%
 
 :- implementation.
 
-:- import_module int, require, std_util.
+:- import_module bool, int, require, std_util.
 
 
 :- type rbtree(K,V)	 --->	empty
@@ -143,6 +181,9 @@
 
 rbtree__init(empty).
 
+rbtree__is_empty(Tree) :-
+	Tree = empty.
+
 %-----------------------------------------------------------------------------%
 
 % Special conditions that must be satisfied by Red-Black trees.
@@ -328,6 +369,7 @@
 
 
 :- pred rbtree__set_2(rbtree(K, V), K, V, rbtree(K, V)). 
+:- mode rbtree__set_2(di, di, di, uo) is det.
 :- mode rbtree__set_2(in, in, in, out) is det.
 
 % rbtree__set_2:
@@ -395,7 +437,10 @@
 					TreeR = red(K0, V0, LRR, R0),
 					Tree = black(LRK, LRV, TreeL, TreeR)
 				;
-					Tree = black(K0, V0, NewL, R0)
+					% NewL2 == NewL, but this hack 
+					% needed for unique modes to work.
+					NewL2 = red(LK, LV, LL, LR),
+					Tree = black(K0, V0, NewL2, R0)
 				)
 			;
 				Tree = black(K0, V0, NewL, R0)
@@ -422,7 +467,10 @@
 					TreeL = red(K0, V0, L0, RL),
 					Tree = black(RK, RV, TreeL, RR)
 				;
-					Tree = black(K0, V0, L0, NewR)
+					% NewR2 == NewR, but this hack 
+					% needed for unique modes to work.
+					NewR2 = red(RK, RV, RL, RR),
+					Tree = black(K0, V0, L0, NewR2)
 				)
 			;
 				Tree = black(K0, V0, L0, NewR)
@@ -584,6 +632,28 @@
 
 %-----------------------------------------------------------------------------%
 
+rbtree__member(empty, _K, _V) :- fail.
+rbtree__member(red(K0, V0, Left, Right), K, V) :-
+	(
+		K = K0,
+		V = V0
+	;
+		rbtree__member(Left, K, V)
+	;
+		rbtree__member(Right, K, V)
+	).
+rbtree__member(black(K0, V0, Left, Right), K, V) :-
+	(
+		K = K0,
+		V = V0
+	;
+		rbtree__member(Left, K, V)
+	;
+		rbtree__member(Right, K, V)
+	).
+
+%-----------------------------------------------------------------------------%
+
 rbtree__search(Tree, K, V) :-
 	( Tree = red(K0, V0, Left, Right)
 	; Tree = black(K0, V0, Left, Right)
@@ -681,18 +751,16 @@
 %-----------------------------------------------------------------------------%
 
 rbtree__delete(Tree0, K, Tree) :-
-	(
-		rbtree__remove(Tree0, K, Tree1)
-	->
-		Tree = Tree1
-	;
-		Tree = Tree0
-	).
-	
-%-----------------------------------------------------------------------------%
+	rbtree__delete_2(Tree0, K, no, _, Tree).
 
-% rbtree_remove:
-%	Search down the tree, looking for the node to remove.  O(log N)
+% rbtree__delete_2(Tree0, Key, MustRemove, MaybeValue, Tree):
+%	Search the tree Tree0, looking for a node with key Key to delete.
+%	If MustRemove is `yes' and we don't find the key, fail.
+%	If we find the key, return it in MaybeValue and delete the node.
+%	Tree is the resulting tree, whether a node was removed or not.
+%
+% Deletion algorithm:
+%	Search down the tree, looking for the node to delete.  O(log N)
 %	When we find it, there are 4 possible conditions ->
 %		* Leaf node
 %		    Remove node  O(1)
@@ -700,84 +768,96 @@
 %		    Move maximum key of Left subtree to current node. O(log N)
 %		* Right subtree of node to be deleted exists
 %		    Move minimum key of Right subtree to current node. O(log N)
-%		* Both of node to be deleted left and right subtree exist
+%		* Both left and right subtrees of node to be deleted exist
 %		    Move maximum key of Left subtree to current node. O(log N)
 %
 %	Algorithm O(log N).
 
-rbtree__remove(empty, _K, _Tree) :-
-	fail.
-rbtree__remove(red(K0, V0, L, R), K, Tree) :-
+:- pred rbtree__delete_2(rbtree(K, V), K, bool, maybe(V), rbtree(K, V)).
+:- mode rbtree__delete_2(di, in, in, uo, uo) is semidet.
+:- mode rbtree__delete_2(di, in, in(bound(no)), uo, uo) is det.
+:- mode rbtree__delete_2(in, in, in, out, out) is semidet.
+:- mode rbtree__delete_2(in, in, in(bound(no)), out, out) is det.
+
+rbtree__delete_2(empty, _K, no, no, empty).
+rbtree__delete_2(red(K0, V0, L, R), K, MustRemove, MaybeV, Tree) :-
 	compare(Result, K, K0),
 	(	
 		Result = (=)
 	->
 		(
-			L = empty
-		->	
+			rbtree__remove_largest(L, NewK, NewV, NewL)
+		->
+			Tree = red(NewK, NewV, NewL, R)
+		;
+			% L must be empty
 			(
-				R = empty
+				rbtree__remove_smallest(R, NewK, NewV, NewR)
 			->
-				Tree = empty
+				Tree = red(NewK, NewV, empty, NewR)
 			;
-				rbtree__get_tree_min(R, NewK, NewV, NewR),
-				Tree = red(NewK, NewV, L, NewR)
+				% R must be empty
+				Tree = empty
 			)
-		;
-			rbtree__get_tree_max(L, NewK, NewV, NewL),
-			Tree = red(NewK, NewV, NewL, R)
-		)
+		),
+		MaybeV = yes(V0)
 	;
 
 		Result = (<)
 	->
-		rbtree__remove(L, K, NewL),
+		rbtree__delete_2(L, K, MustRemove, MaybeV, NewL),
 		Tree = red(K0, V0, NewL, R)
 	;
-		rbtree__remove(R, K, NewR),
+		rbtree__delete_2(R, K, MustRemove, MaybeV, NewR),
 		Tree = red(K0, V0, L, NewR)
 	).
-rbtree__remove(black(K0, V0, L, R), K, Tree) :-
+rbtree__delete_2(black(K0, V0, L, R), K, MustRemove, MaybeV, Tree) :-
 	compare(Result, K, K0),
 	(	
 		Result = (=)
 	->
 		(
-			L = empty
-		->	
+			rbtree__remove_largest(L, NewK, NewV, NewL)
+		->
+			Tree = black(NewK, NewV, NewL, R)
+		;
+			% L must be empty
 			(
-				R = empty
+				rbtree__remove_smallest(R, NewK, NewV, NewR)
 			->
-				Tree = empty
+				Tree = black(NewK, NewV, empty, NewR)
 			;
-				rbtree__get_tree_min(R, NewK, NewV, NewR),
-				Tree = black(NewK, NewV, L, NewR)
+				% R must be empty
+				Tree = empty
 			)
-		;
-			rbtree__get_tree_max(L, NewK, NewV, NewL),
-			Tree = black(NewK, NewV, NewL, R)
-		)
+		),
+		MaybeV = yes(V0)
 	;
 
 		Result = (<)
 	->
-		rbtree__remove(L, K, NewL),
+		rbtree__delete_2(L, K, MustRemove, MaybeV, NewL),
 		Tree = black(K0, V0, NewL, R)
 	;
-		rbtree__remove(R, K, NewR),
+		rbtree__delete_2(R, K, MustRemove, MaybeV, NewR),
 		Tree = black(K0, V0, L, NewR)
 	).
 
-% rbtree__get_tree_max:
+%-----------------------------------------------------------------------------%
+
+rbtree__remove(Tree0, K, V, Tree) :-
+	rbtree__delete_2(Tree0, K, yes, yes(V), Tree).
+
+rbtree__remove(Tree0, K, Tree) :-
+	rbtree__remove(Tree0, K, _, Tree).
+
+% rbtree__remove_largest:
 %	Deletes the node with the maximum K from the tree, and returns the
 %	key and value fields.
 
-:- pred rbtree__get_tree_max(rbtree(K, V), K, V, rbtree(K, V)).
-:- mode rbtree__get_tree_max(in, out, out, out) is det.
-
-rbtree__get_tree_max(empty, _K, _V, _Tree) :-
-	error("rbtree__get_tree_max: attempted to get K+V from empty tree").
-rbtree__get_tree_max(red(K0, V0, L, R), NewK, NewV, Tree) :-
+rbtree__remove_largest(empty, _K, _V, _Tree) :-
+	fail.
+rbtree__remove_largest(red(K0, V0, L, R), NewK, NewV, Tree) :-
 	(
 		R = empty
 	->
@@ -785,10 +865,10 @@
 		NewV = V0,
 		Tree = L
 	;
-		rbtree__get_tree_max(R, NewK, NewV, NewR),
+		rbtree__remove_largest(R, NewK, NewV, NewR),
 		Tree = red(K0, V0, L, NewR)
 	).
-rbtree__get_tree_max(black(K0, V0, L, R), NewK, NewV, Tree) :-
+rbtree__remove_largest(black(K0, V0, L, R), NewK, NewV, Tree) :-
 	(
 		R = empty
 	->
@@ -796,20 +876,17 @@
 		NewV = V0,
 		Tree = L
 	;
-		rbtree__get_tree_max(R, NewK, NewV, NewR),
+		rbtree__remove_largest(R, NewK, NewV, NewR),
 		Tree = black(K0, V0, L, NewR)
 	).
 
-% rbtree__get_tree_min:
+% rbtree__remove_smallest:
 %	Deletes the node with the minimum K from the tree, and returns the
 %	key and value fields.
 
-:- pred rbtree__get_tree_min(rbtree(K, V), K, V, rbtree(K, V)).
-:- mode rbtree__get_tree_min(in, out, out, out) is det.
-
-rbtree__get_tree_min(empty, _K, _V, _Tree) :-
-	error("rbtree__get_tree_min: attempted to get K+V from empty tree").
-rbtree__get_tree_min(red(K0, V0, L, R), NewK, NewV, Tree) :-
+rbtree__remove_smallest(empty, _K, _V, _Tree) :-
+	fail.
+rbtree__remove_smallest(red(K0, V0, L, R), NewK, NewV, Tree) :-
 	(
 		L = empty
 	->
@@ -817,10 +894,10 @@
 		NewV = V0,
 		Tree = R
 	;
-		rbtree__get_tree_min(L, NewK, NewV, NewL),
+		rbtree__remove_smallest(L, NewK, NewV, NewL),
 		Tree = red(K0, V0, NewL, R)
 	).
-rbtree__get_tree_min(black(K0, V0, L, R), NewK, NewV, Tree) :-
+rbtree__remove_smallest(black(K0, V0, L, R), NewK, NewV, Tree) :-
 	(
 		L = empty
 	->
@@ -828,7 +905,7 @@
 		NewV = V0,
 		Tree = R
 	;
-		rbtree__get_tree_min(L, NewK, NewV, NewL),
+		rbtree__remove_smallest(L, NewK, NewV, NewL),
 		Tree = black(K0, V0, NewL, R)
 	).
 
@@ -890,6 +967,34 @@
 	list__append(L0, [K0 - V0|L1], L).
 
 %-----------------------------------------------------------------------------%
+
+rbtree__foldl(_Pred, empty, Acc, Acc).
+rbtree__foldl(Pred, red(K, V, Left, Right), Acc0, Acc) :-
+	rbtree__foldl(Pred, Left, Acc0, Acc1),
+	call(Pred, K, V, Acc1, Acc2),
+	rbtree__foldl(Pred, Right, Acc2, Acc).
+rbtree__foldl(Pred, black(K, V, Left, Right), Acc0, Acc) :-
+	rbtree__foldl(Pred, Left, Acc0, Acc1),
+	call(Pred, K, V, Acc1, Acc2),
+	rbtree__foldl(Pred, Right, Acc2, Acc).
+
+%-----------------------------------------------------------------------------%
+
+rbtree__map_values(_Pred, empty, empty).
+rbtree__map_values(Pred, Tree0, Tree) :-
+	Tree0 = red(K0, V0, Left0, Right0),
+	Tree  = red(K0, W0, Left, Right),
+	call(Pred, K0, V0, W0),
+	rbtree__map_values(Pred, Left0, Left),
+	rbtree__map_values(Pred, Right0, Right).
+rbtree__map_values(Pred, Tree0, Tree) :-
+	Tree0 = black(K0, V0, Left0, Right0),
+	Tree  = black(K0, W0, Left, Right),
+	call(Pred, K0, V0, W0),
+	rbtree__map_values(Pred, Left0, Left),
+	rbtree__map_values(Pred, Right0, Right).
+
+%-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 % Ralph Becket <rwab1 at cl.cam.ac.uk> 29/04/99
 % 	Function forms added.
@@ -916,6 +1021,10 @@
 
 :- func rbtree__rbtree_to_assoc_list(rbtree(K, V)) = assoc_list(K, V).
 
+:- func rbtree__foldl(func(K, V, T) = T, rbtree(K, V), T) = T.
+
+:- func rbtree__map_values(func(K, V) = W, rbtree(K, V)) = rbtree(K, W).
+
 % ---------------------------------------------------------------------------- %
 % ---------------------------------------------------------------------------- %
 
@@ -951,4 +1060,11 @@
 rbtree__rbtree_to_assoc_list(RBT) = AL :-
 	rbtree__rbtree_to_assoc_list(RBT, AL).
 
+rbtree__foldl(F, T, A) = B :-
+	P = ( pred(W::in, X::in, Y::in, Z::out) is det :- Z = F(W, X, Y) ),
+	rbtree__foldl(P, T, A, B).
+
+rbtree__map_values(F, T1) = T2 :-
+	P = ( pred(X::in, Y::in, Z::out) is det :- Z = F(X, Y) ),
+	rbtree__map_values(P, T1, T2).
 


More information about the developers mailing list