aboutsummaryrefslogtreecommitdiffhomepage
path: root/lib
diff options
context:
space:
mode:
authorGravatar Gabriel Scherer <gabriel.scherer@gmail.com>2015-06-27 22:01:38 +0200
committerGravatar Maxime Dénès <mail@maximedenes.fr>2016-06-27 12:45:41 +0200
commit56a7d450fb67268d121e69a5e111968d0dfb2a6a (patch)
tree98485b86b0505cefc082c37f074932ff8eaa02a4 /lib
parent39163205cc59b98028eaaeace86463bb8c990818 (diff)
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/cList.ml9
-rw-r--r--lib/cList.mli4
2 files changed, 13 insertions, 0 deletions
diff --git a/lib/cList.ml b/lib/cList.ml
index 3a792d416..602bba6a5 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 b19d1a80f..bc8749b4f 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 *)