add CCSimple_queue to containers.data

This commit is contained in:
Simon Cruanes 2017-05-10 08:58:51 +02:00
parent f7394ede9f
commit d6120d4784
4 changed files with 140 additions and 1 deletions

2
_oasis
View file

@ -67,7 +67,7 @@ Library "containers_data"
CCPersistentHashtbl, CCDeque, CCFQueue, CCBV, CCMixtbl, CCPersistentHashtbl, CCDeque, CCFQueue, CCBV, CCMixtbl,
CCMixmap, CCRingBuffer, CCIntMap, CCPersistentArray, CCMixmap, CCRingBuffer, CCIntMap, CCPersistentArray,
CCMixset, CCGraph, CCHashSet, CCBitField, CCMixset, CCGraph, CCHashSet, CCBitField,
CCHashTrie, CCWBTree, CCRAL, CCHashTrie, CCWBTree, CCRAL, CCSimple_queue,
CCImmutArray, CCHet, CCZipper CCImmutArray, CCHet, CCZipper
BuildDepends: bytes BuildDepends: bytes
# BuildDepends: bytes, bisect_ppx # BuildDepends: bytes, bisect_ppx

View file

@ -93,6 +93,7 @@ CCPersistentArray
CCPersistentHashtbl CCPersistentHashtbl
CCRAL CCRAL
CCRingBuffer CCRingBuffer
CCSimple_queue
CCTrie CCTrie
CCWBTree CCWBTree
} }

View file

@ -0,0 +1,79 @@
(* This file is free software, part of containers. See file "license" for more details. *)
(** {1 Functional queues (fifo)} *)
type 'a t = {
hd : 'a list;
tl : 'a list;
} (** Queue containing elements of type 'a *)
let empty = {
hd = [];
tl = [];
}
(* invariant: if hd=[], then tl=[] *)
let _make hd tl = match hd with
| [] -> {hd=List.rev tl; tl=[] }
| _::_ -> {hd; tl; }
let is_empty q = q.hd = []
let push x q = {q with tl = x :: q.tl; }
let snoc q x = push x q
let peek_exn q =
match q.hd with
| [] -> assert (q.tl = []); raise (Invalid_argument "Queue.peek")
| x::_ -> x
let peek q = match q.hd with
| [] -> None
| x::_ -> Some x
let pop_exn q =
match q.hd with
| [] -> assert (q.tl = []); raise (Invalid_argument "Queue.peek")
| x::hd' ->
let q' = _make hd' q.tl in
x, q'
let pop q =
try Some (pop_exn q)
with Invalid_argument _ -> None
let junk q =
try
let _, q' = pop_exn q in
q'
with Invalid_argument _ -> q
(** Append two queues. Elements from the second one come
after elements of the first one *)
let append q1 q2 =
{ hd=q1.hd;
tl=q2.tl @ (List.rev_append q2.hd q1.tl);
}
let map f q = { hd=List.map f q.hd; tl=List.map f q.tl; }
let size q = List.length q.hd + List.length q.tl
let (>|=) q f = map f q
let fold f acc q =
let acc' = List.fold_left f acc q.hd in
List.fold_right (fun x acc -> f acc x) q.tl acc'
let iter f q = fold (fun () x -> f x) () q
type 'a sequence = ('a -> unit) -> unit
let to_seq q = fun k -> iter k q
let of_seq seq =
let q = ref empty in
seq (fun x -> q := push x !q);
!q

View file

@ -0,0 +1,59 @@
(* This file is free software, part of containers. See file "license" for more details. *)
(** {1 Functional queues (fifo)} *)
(** Simple implementation of functional queues
@since NEXT_RELEASE *)
type +'a t
(** Queue containing elements of type 'a *)
val empty : 'a t
val is_empty : 'a t -> bool
val push : 'a -> 'a t -> 'a t
(** Push element at the end of the queue *)
val snoc : 'a t -> 'a -> 'a t
(** Flip version of {!push} *)
val peek : 'a t -> 'a option
(** First element of the queue *)
val peek_exn : 'a t -> 'a
(** Same as {!peek} but
@raise Invalid_argument if the queue is empty *)
val pop : 'a t -> ('a * 'a t) option
(** Get and remove the first element *)
val pop_exn : 'a t -> ('a * 'a t)
(** Same as {!pop}, but fails on empty queues.
@raise Invalid_argument if the queue is empty *)
val junk : 'a t -> 'a t
(** Remove first element. If the queue is empty, do nothing. *)
val append : 'a t -> 'a t -> 'a t
(** Append two queues. Elements from the second one come
after elements of the first one.
Linear in the size of the second queue. *)
val map : ('a -> 'b) -> 'a t -> 'b t
(** Map values *)
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
val size : 'a t -> int
(** Number of elements in the queue (linear in time) *)
val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b
val iter : ('a -> unit) -> 'a t -> unit
type 'a sequence = ('a -> unit) -> unit
val to_seq : 'a t -> 'a sequence
val of_seq : 'a sequence -> 'a t