From 56a7d450fb67268d121e69a5e111968d0dfb2a6a Mon Sep 17 00:00:00 2001 From: Gabriel Scherer Date: Sat, 27 Jun 2015 22:01:38 +0200 Subject: add CList.extract_first we already have val remove_first : ('a -> bool) -> 'a list -> 'a list (** Remove the first element satisfying a predicate, or raise [Not_found] *) now we also have the more general val extract_first : ('a -> bool) -> 'a list -> 'a list * 'a (** Remove and return the first element satisfying a predicate, or raise [Not_found] *) The implementation is tail-recursive. The code I'm hoping to factorize reimplements extract_first in a tail-recursive way, so it seemed good to preserve this. On the other hand remove_first is not tail-recursive itself, and that gives better constant factors in real-life cases. It's unclear what is the best choice. --- lib/cList.ml | 9 +++++++++ lib/cList.mli | 4 ++++ 2 files changed, 13 insertions(+) (limited to 'lib') diff --git a/lib/cList.ml b/lib/cList.ml index 3a792d4168..602bba6a5c 100644 --- a/lib/cList.ml +++ b/lib/cList.ml @@ -65,6 +65,7 @@ sig val except : 'a eq -> 'a -> 'a list -> 'a list val remove : 'a eq -> 'a -> 'a list -> 'a list val remove_first : ('a -> bool) -> 'a list -> 'a list + val extract_first : ('a -> bool) -> 'a list -> 'a list * 'a val insert : ('a -> 'a -> bool) -> 'a -> 'a list -> 'a list val for_all2eq : ('a -> 'b -> bool) -> 'a list -> 'b list -> bool val sep_last : 'a list -> 'a * 'a list @@ -461,6 +462,14 @@ let rec remove_first p = function | b::l -> b::remove_first p l | [] -> raise Not_found +let extract_first p li = + let rec loop rev_left = function + | [] -> raise Not_found + | x::right -> + if p x then List.rev_append rev_left right, x + else loop (x :: rev_left) right + in loop [] li + let insert p v l = let rec insrec = function | [] -> [v] diff --git a/lib/cList.mli b/lib/cList.mli index b19d1a80fc..bc8749b4f8 100644 --- a/lib/cList.mli +++ b/lib/cList.mli @@ -125,6 +125,10 @@ sig val remove_first : ('a -> bool) -> 'a list -> 'a list (** Remove the first element satisfying a predicate, or raise [Not_found] *) + val extract_first : ('a -> bool) -> 'a list -> 'a list * 'a + (** Remove and return the first element satisfying a predicate, + or raise [Not_found] *) + val insert : ('a -> 'a -> bool) -> 'a -> 'a list -> 'a list (** Insert at the (first) position so that if the list is ordered wrt to the total order given as argument, the order is preserved *) -- cgit v1.2.3