[Libguestfs] [PATCH v3 4/8] mllib: Add some imperative list manipulation functions.

Richard W.M. Jones rjones at redhat.com
Thu Jul 7 16:30:03 UTC 2016


This adds imperative list manipulation functions inspired by Perl.
The functions are passed list refs which get updated in place.

This allows us to replace some awkward pure functional code like:

  let xs = ys in
  let xs = if foo then xs @ zs else xs in

with:

  let xs = ref ys in
  if foo then append xs zs;
---
 mllib/common_utils.ml  | 20 ++++++++++++++++++++
 mllib/common_utils.mli | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml
index 77b9acd..40a19bc 100644
--- a/mllib/common_utils.ml
+++ b/mllib/common_utils.ml
@@ -282,6 +282,26 @@ let sort_uniq ?(cmp = Pervasives.compare) xs =
   let xs = uniq ~cmp xs in
   xs
 
+let push xsp x = xsp := !xsp @ [x]
+let unshift x xsp = xsp := x :: !xsp
+let pop xsp =
+  let x, xs =
+    match List.rev !xsp with
+    | x :: xs -> x, xs
+    | [] -> failwith "pop" in
+  xsp := List.rev xs;
+  x
+let shift xsp =
+  let x, xs =
+    match !xsp with
+    | x :: xs -> x, xs
+    | [] -> failwith "shift" in
+  xsp := xs;
+  x
+
+let append xsp xs = xsp := !xsp @ xs
+let prepend xs xsp = xsp := xs @ !xsp
+
 let may f = function
   | None -> ()
   | Some x -> f x
diff --git a/mllib/common_utils.mli b/mllib/common_utils.mli
index 5b0b9bb..97c7d9f 100644
--- a/mllib/common_utils.mli
+++ b/mllib/common_utils.mli
@@ -141,6 +141,42 @@ val uniq : ?cmp:('a -> 'a -> int) -> 'a list -> 'a list
 val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a list -> 'a list
 (** Sort and uniquify a list. *)
 
+val push : 'a list ref -> 'a -> unit
+val unshift : 'a -> 'a list ref -> unit
+val pop : 'a list ref -> 'a
+val shift : 'a list ref -> 'a
+(** Imperative list manipulation functions, similar to the Perl
+    functions described in http://perlmaven.com/manipulating-perl-arrays
+
+    These operate on list references, and each function modifies the
+    list reference that is passed to it.
+
+    [push xsp x] appends the element [x] to the end of the list [xsp].
+    This function is not tail-recursive.
+
+    [unshift x xsp] prepends the element [x] to the head of the list [xsp].
+    (The arguments are reversed compared to the same Perl function, but
+    OCaml is type safe so that's OK.)
+
+    [pop xsp] removes the last element of the list [xsp] and returns it.
+    The list is modified to become the list minus the final element.
+    If a zero-length list is passed in, this raises [Failure "pop"].
+    This function is not tail-recursive.
+
+    [shift xsp] removes the head element of the list [xsp] and returns it.
+    The list is modified to become the tail of the list.  If a zero-length
+    list is passed in, this raises [Failure "shift"]. *)
+
+val append : 'a list ref -> 'a list -> unit
+val prepend : 'a list -> 'a list ref -> unit
+(** More imperative list manipulation functions.
+
+    [append] is like {!push} above, except it appends a list to
+    the list reference.  This function is not tail-recursive.
+
+    [prepend] is like {!unshift} above, except it prepends a list
+    to the list reference. *)
+
 val may : ('a -> unit) -> 'a option -> unit
 (** [may f (Some x)] runs [f x].  [may f None] does nothing. *)
 
-- 
2.7.4




More information about the Libguestfs mailing list