From b45153a25cc6cc96fd708067ab3664779d442416 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 13 Jan 2017 11:23:49 +0100 Subject: [PATCH 01/11] add `doc` and `test` to opam --- opam | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/opam b/opam index 4b4684e..4081978 100644 --- a/opam +++ b/opam @@ -11,6 +11,14 @@ build: [ ] [make "build"] ] +build-doc: [ + ["./configure" "--enable-docs"] + [make "doc"] +] +build-test: [ + ["./configure" "--enable-tests"] + [make "test"] +] install: [make "install"] remove: [ ["ocamlfind" "remove" "sequence"] From fa26fa0f274199dbd3a8d5f472dbd16075409eae Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Thu, 2 Feb 2017 21:20:27 +0100 Subject: [PATCH 02/11] rename files --- src/{sequence.ml => Sequence.ml} | 0 src/{sequence.mli => Sequence.mli} | 0 src/sequenceLabels.ml | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) rename src/{sequence.ml => Sequence.ml} (100%) rename src/{sequence.mli => Sequence.mli} (100%) diff --git a/src/sequence.ml b/src/Sequence.ml similarity index 100% rename from src/sequence.ml rename to src/Sequence.ml diff --git a/src/sequence.mli b/src/Sequence.mli similarity index 100% rename from src/sequence.mli rename to src/Sequence.mli diff --git a/src/sequenceLabels.ml b/src/sequenceLabels.ml index 663d7cb..b990b32 120000 --- a/src/sequenceLabels.ml +++ b/src/sequenceLabels.ml @@ -1 +1 @@ -sequence.ml \ No newline at end of file +Sequence.ml \ No newline at end of file From 12743ab24f1d5389a09adabfb0513c7c4b164c10 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Thu, 2 Feb 2017 21:27:46 +0100 Subject: [PATCH 03/11] add `count` --- src/Sequence.ml | 22 ++++++++++++++++++++++ src/Sequence.mli | 6 ++++++ src/sequenceLabels.mli | 6 ++++++ 3 files changed, 34 insertions(+) diff --git a/src/Sequence.ml b/src/Sequence.ml index 425bf8d..d36221d 100644 --- a/src/Sequence.ml +++ b/src/Sequence.ml @@ -411,6 +411,28 @@ let group_by (type k) ?(hash=Hashtbl.hash) ?(eq=(=)) seq = |> OUnit.assert_equal [[1];[2;2;2];[3;3;3];[4]] *) +let count (type k) ?(hash=Hashtbl.hash) ?(eq=(=)) seq = + let module Tbl = Hashtbl.Make(struct + type t = k + let equal = eq + let hash = hash + end) in + (* compute group table *) + let tbl = Tbl.create 32 in + seq + (fun x -> + let n = try Tbl.find tbl x with Not_found -> 0 in + Tbl.replace tbl x (n+1) + ); + fun yield -> + Tbl.iter (fun x n -> yield (x,n)) tbl + +(*$R + [1;2;3;3;2;2;3;4] + |> of_list |> count ?eq:None ?hash:None |> sort ?cmp:None |> to_list + |> OUnit.assert_equal [1,1;2,3;3,3;4,1] +*) + let uniq ?(eq=fun x y -> x = y) seq k = let has_prev = ref false and prev = ref (Obj.magic 0) in (* avoid option type, costly *) diff --git a/src/Sequence.mli b/src/Sequence.mli index e7c5e3d..872289d 100644 --- a/src/Sequence.mli +++ b/src/Sequence.mli @@ -241,6 +241,12 @@ val group_by : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) -> The result sequence is traversable as many times as required. @since 0.6 *) +val count : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) -> + 'a t -> ('a * int) t +(** Map each distinct element to its number of occurrences in the whole seq. + Similar to [group_by seq |> map (fun l->List.hd l, List.length l)] + @since NEXT_RELEASE *) + val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t (** Remove consecutive duplicate elements. Basically this is like [fun seq -> map List.hd (group seq)]. *) diff --git a/src/sequenceLabels.mli b/src/sequenceLabels.mli index 06bd60f..2829be4 100644 --- a/src/sequenceLabels.mli +++ b/src/sequenceLabels.mli @@ -212,6 +212,12 @@ val group_by : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) -> The result sequence is traversable as many times as required. @since 0.6 *) +val count : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) -> + 'a t -> ('a * int) t +(** Map each distinct element to its number of occurrences in the whole seq. + Similar to [group_by seq |> map (fun l->List.hd l, List.length l)] + @since NEXT_RELEASE *) + val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t (** Remove consecutive duplicate elements. Basically this is like [fun seq -> map List.hd (group seq)]. *) From ffe157a1c6954f2becbbef32e680232015bd0274 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Thu, 2 Feb 2017 21:29:32 +0100 Subject: [PATCH 04/11] add `{max_exn,min_exn}` --- src/Sequence.ml | 13 +++++++++++++ src/Sequence.mli | 10 ++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/Sequence.ml b/src/Sequence.ml index d36221d..af6ff4e 100644 --- a/src/Sequence.ml +++ b/src/Sequence.ml @@ -554,6 +554,10 @@ let max ?(lt=fun x y -> x < y) seq = | Some y -> if lt y x then ret := Some x); !ret +let max_exn ?lt seq = match max ?lt seq with + | Some x -> x + | None -> raise Not_found + let min ?(lt=fun x y -> x < y) seq = let ret = ref None in seq @@ -562,6 +566,15 @@ let min ?(lt=fun x y -> x < y) seq = | Some y -> if lt x y then ret := Some x); !ret +let min_exn ?lt seq = match min ?lt seq with + | Some x -> x + | None -> raise Not_found + +(*$= & ~printer:string_of_int + 100 (0 -- 100 |> max_exn ?lt:None) + 0 (0 -- 100 |> min_exn ?lt:None) +*) + exception ExitHead let head seq = diff --git a/src/Sequence.mli b/src/Sequence.mli index 872289d..d52cdac 100644 --- a/src/Sequence.mli +++ b/src/Sequence.mli @@ -290,10 +290,20 @@ val max : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option @return None if the sequence is empty, Some [m] where [m] is the maximal element otherwise *) +val max_exn : ?lt:('a -> 'a -> bool) -> 'a t -> 'a +(** Unsafe version of {!max} + @raise Not_found if the sequence is empty + @since NEXT_RELEASE *) + val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option (** Min element of the sequence, using the given comparison function. see {!max} for more details. *) +val min_exn : ?lt:('a -> 'a -> bool) -> 'a t -> 'a +(** Unsafe version of {!min} + @raise Not_found if the sequence is empty + @since NEXT_RELEASE *) + val head : 'a t -> 'a option (** First element, if any, otherwise [None] @since 0.5.1 *) From a41a997c8ff0bc0111123e3510d46848f98f2d6b Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Thu, 2 Feb 2017 21:32:00 +0100 Subject: [PATCH 05/11] add `find_map{,i}` as better alias to existing functions --- src/Sequence.ml | 10 +++++++--- src/Sequence.mli | 8 ++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Sequence.ml b/src/Sequence.ml index af6ff4e..485a7b2 100644 --- a/src/Sequence.ml +++ b/src/Sequence.ml @@ -699,7 +699,7 @@ let mem ?(eq=(=)) x seq = exists (eq x) seq exception ExitFind -let find f seq = +let find_map f seq = let r = ref None in begin try @@ -711,7 +711,9 @@ let find f seq = end; !r -let findi f seq = +let find = find_map + +let find_mapi f seq = let i = ref 0 in let r = ref None in begin @@ -724,7 +726,9 @@ let findi f seq = end; !r -let find_pred f seq = find (fun x -> if f x then Some x else None) seq +let findi = find_mapi + +let find_pred f seq = find_map (fun x -> if f x then Some x else None) seq let find_pred_exn f seq = match find_pred f seq with | Some x -> x diff --git a/src/Sequence.mli b/src/Sequence.mli index d52cdac..15d394a 100644 --- a/src/Sequence.mli +++ b/src/Sequence.mli @@ -144,10 +144,18 @@ val find : ('a -> 'b option) -> 'a t -> 'b option (** Find the first element on which the function doesn't return [None] @since 0.5 *) +val find_map : ('a -> 'b option) -> 'a t -> 'b option +(** Alias to {!find} + @since NEXT_RELEASE *) + val findi : (int -> 'a -> 'b option) -> 'a t -> 'b option (** Indexed version of {!find} @since 0.9 *) +val find_mapi : (int -> 'a -> 'b option) -> 'a t -> 'b option +(** Alias to {!findi} + @since NEXT_RELEASE *) + val find_pred : ('a -> bool) -> 'a t -> 'a option (** [find_pred p l] finds the first element of [l] that satisfies [p], or returns [None] if no element satisfies [p] From 6c7d59042abad212600aba0325d98d1907b5727f Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Thu, 2 Feb 2017 21:54:33 +0100 Subject: [PATCH 06/11] add `{join_by,join_all_by,group_join_by}` --- src/Sequence.ml | 93 ++++++++++++++++++++++++++++++++++++++++++++++++ src/Sequence.mli | 46 ++++++++++++++++++++++++ 2 files changed, 139 insertions(+) diff --git a/src/Sequence.ml b/src/Sequence.ml index 485a7b2..da7daa8 100644 --- a/src/Sequence.ml +++ b/src/Sequence.ml @@ -15,6 +15,9 @@ type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit let pp_ilist = Q.Print.(list int) *) +type 'a equal = 'a -> 'a -> bool +type 'a hash = 'a -> int + (** Build a sequence from a iter function *) let from_iter f = f @@ -521,6 +524,96 @@ let join ~join_row s1 s2 k = OUnit.assert_equal ["1 = 1"; "2 = 2"] (to_list s); *) +let join_by (type a) ?(eq=(=)) ?(hash=Hashtbl.hash) f1 f2 ~merge c1 c2 = + let module Tbl = Hashtbl.Make(struct + type t = a + let equal = eq + let hash = hash + end) in + let tbl = Tbl.create 32 in + c1 + (fun x -> + let key = f1 x in + Tbl.add tbl key x); + let res = ref [] in + c2 + (fun y -> + let key = f2 y in + let xs = Tbl.find_all tbl key in + List.iter + (fun x -> match merge key x y with + | None -> () + | Some z -> res := z :: !res) + xs); + fun yield -> List.iter yield !res + +type ('a, 'b) join_all_cell = { + mutable ja_left: 'a list; + mutable ja_right: 'b list; +} + +let join_all_by (type a) ?(eq=(=)) ?(hash=Hashtbl.hash) f1 f2 ~merge c1 c2 = + let module Tbl = Hashtbl.Make(struct + type t = a + let equal = eq + let hash = hash + end) in + let tbl = Tbl.create 32 in + (* build the map [key -> cell] *) + c1 + (fun x -> + let key = f1 x in + try + let c = Tbl.find tbl key in + c.ja_left <- x :: c.ja_left + with Not_found -> + Tbl.add tbl key {ja_left=[x]; ja_right=[]}); + c2 + (fun y -> + let key = f2 y in + try + let c = Tbl.find tbl key in + c.ja_right <- y :: c.ja_right + with Not_found -> + Tbl.add tbl key {ja_left=[]; ja_right=[y]}); + let res = ref [] in + Tbl.iter + (fun key cell -> match merge key cell.ja_left cell.ja_right with + | None -> () + | Some z -> res := z :: !res) + tbl; + fun yield -> List.iter yield !res + +let group_join_by (type a) ?(eq=(=)) ?(hash=Hashtbl.hash) f c1 c2 = + let module Tbl = Hashtbl.Make(struct + type t = a + let equal = eq + let hash = hash + end) in + let tbl = Tbl.create 32 in + c1 (fun x -> Tbl.replace tbl x []); + c2 + (fun y -> + (* project [y] into some element of [c1] *) + let key = f y in + try + let l = Tbl.find tbl key in + Tbl.replace tbl key (y :: l) + with Not_found -> ()); + fun yield -> Tbl.iter (fun k l -> yield (k,l)) tbl + +(*$= + ['a', ["abc"; "attic"]; \ + 'b', ["barbary"; "boom"; "bop"]; \ + 'c', []] \ + (group_join_by (fun s->s.[0]) \ + (of_str "abc") \ + (of_list ["abc"; "boom"; "attic"; "deleted"; "barbary"; "bop"]) \ + |> map (fun (c,l)->c,List.sort Pervasives.compare l) \ + |> sort |> to_list) +*) + + let rec unfoldr f b k = match f b with | None -> () | Some (x, b') -> diff --git a/src/Sequence.mli b/src/Sequence.mli index 15d394a..1d6509a 100644 --- a/src/Sequence.mli +++ b/src/Sequence.mli @@ -39,6 +39,9 @@ type +'a sequence = 'a t type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit (** Sequence of pairs of values of type ['a] and ['b]. *) +type 'a equal = 'a -> 'a -> bool +type 'a hash = 'a -> int + (** {2 Build a sequence} *) val from_iter : (('a -> unit) -> unit) -> 'a t @@ -285,6 +288,49 @@ val join : join_row:('a -> 'b -> 'c option) -> 'a t -> 'b t -> 'c t the two elements do not combine. Assume that [b] allows for multiple iterations. *) +val join_by : ?eq:'key equal -> ?hash:'key hash -> + ('a -> 'key) -> ('b -> 'key) -> + merge:('key -> 'a -> 'b -> 'c option) -> + 'a t -> + 'b t -> + 'c t +(** [join key1 key2 ~merge] is a binary operation + that takes two sequences [a] and [b], projects their + elements resp. with [key1] and [key2], and combine + values [(x,y)] from [(a,b)] with the same [key] + using [merge]. If [merge] returns [None], the combination + of values is discarded. + @since NEXT_RELEASE *) + +val join_all_by : ?eq:'key equal -> ?hash:'key hash -> + ('a -> 'key) -> ('b -> 'key) -> + merge:('key -> 'a list -> 'b list -> 'c option) -> + 'a t -> + 'b t -> + 'c t +(** [join_all_by key1 key2 ~merge] is a binary operation + that takes two sequences [a] and [b], projects their + elements resp. with [key1] and [key2], and, for each key [k] + occurring in at least one of them: + - compute the list [l1] of elements of [a] that map to [k] + - compute the list [l2] of elements of [b] that map to [k] + - call [merge k l1 l2]. If [merge] returns [None], the combination + of values is discarded, otherwise it returns [Some c] + and [c] is inserted in the result. + @since NEXT_RELEASE *) + +val group_join_by : ?eq:'a equal -> ?hash:'a hash -> + ('b -> 'a) -> + 'a t -> + 'b t -> + ('a * 'b list) t +(** [group_join_by key2] associates to every element [x] of + the first sequence, all the elements [y] of the second + sequence such that [eq x (key y)]. Elements of the first + sequences without corresponding values in the second one + are mapped to [[]] + @since NEXT_RELEASE *) + val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t (** [unfoldr f b] will apply [f] to [b]. If it yields [Some (x,b')] then [x] is returned From 40f33f6f969bae0288d6be4fe8e1e7fee36f4b98 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Thu, 2 Feb 2017 22:04:29 +0100 Subject: [PATCH 07/11] add `{union,inter,diff,subset}` --- src/Sequence.ml | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/Sequence.mli | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/src/Sequence.ml b/src/Sequence.ml index da7daa8..3bdb9fc 100644 --- a/src/Sequence.ml +++ b/src/Sequence.ml @@ -613,6 +613,52 @@ let group_join_by (type a) ?(eq=(=)) ?(hash=Hashtbl.hash) f c1 c2 = |> sort |> to_list) *) +let union (type a) ?(eq=(=)) ?(hash=Hashtbl.hash) c1 c2 = + let module Tbl = Hashtbl.Make(struct + type t = a let equal = eq let hash = hash end) in + let tbl = Tbl.create 32 in + c1 (fun x -> Tbl.replace tbl x ()); + c2 (fun x -> Tbl.replace tbl x ()); + fun yield -> Tbl.iter (fun x _ -> yield x) tbl + +type inter_status = + | Inter_left + | Inter_both + +let inter (type a) ?(eq=(=)) ?(hash=Hashtbl.hash) c1 c2 = + let module Tbl = Hashtbl.Make(struct + type t = a let equal = eq let hash = hash end) in + let tbl = Tbl.create 32 in + c1 (fun x -> Tbl.replace tbl x Inter_left); + c2 + (fun x -> + try + match Tbl.find tbl x with + | Inter_left -> + Tbl.replace tbl x Inter_both; (* save *) + | Inter_both -> () + with Not_found -> ()); + fun yield -> Tbl.iter (fun x res -> if res=Inter_both then yield x) tbl + +let diff (type a) ?(eq=(=)) ?(hash=Hashtbl.hash) c1 c2 = + let module Tbl = Hashtbl.Make(struct + type t = a let equal = eq let hash = hash end) in + let tbl = Tbl.create 32 in + c2 (fun x -> Tbl.replace tbl x ()); + fun yield -> + c1 (fun x -> if not (Tbl.mem tbl x) then yield x) + +exception Subset_exit + +let subset (type a) ?(eq=(=)) ?(hash=Hashtbl.hash) c1 c2 = + let module Tbl = Hashtbl.Make(struct + type t = a let equal = eq let hash = hash end) in + let tbl = Tbl.create 32 in + c2 (fun x -> Tbl.replace tbl x ()); + try + c1 (fun x -> if not (Tbl.mem tbl x) then raise Subset_exit); + true + with Subset_exit -> false let rec unfoldr f b k = match f b with | None -> () diff --git a/src/Sequence.mli b/src/Sequence.mli index 1d6509a..fb16c81 100644 --- a/src/Sequence.mli +++ b/src/Sequence.mli @@ -331,6 +331,50 @@ val group_join_by : ?eq:'a equal -> ?hash:'a hash -> are mapped to [[]] @since NEXT_RELEASE *) +val inter : + ?eq:'a equal -> ?hash:'a hash -> + 'a t -> 'a t -> 'a t +(** Intersection of two collections. Each element will occur at most once + in the result. Eager. + @since NEXT_RELEASE *) + +(*$= + [2;4;5;6] (inter (1--6) (cons 2 (4--10)) |> sort |> to_list) + [] (inter (0--5) (6--10) |> to_list) +*) + +val union : + ?eq:'a equal -> ?hash:'a hash -> + 'a t -> 'a t -> 'a t +(** Union of two collections. Each element will occur at most once + in the result. Eager. + @since NEXT_RELEASE *) + +(*$= + [2;4;5;6] (union (4--6) (cons 2 (4--5)) |> sort |> to_list) +*) + +val diff : + ?eq:'a equal -> ?hash:'a hash -> + 'a t -> 'a t -> 'a t +(** Set difference. Eager. + @since NEXT_RELEASE *) + +(*$= + [1;2;8;9;10] (diff (1--10) (3--7) |> to_list) +*) + +val subset : + ?eq:'a equal -> ?hash:'a hash -> + 'a t -> 'a t -> bool +(** [subset a b] returns [true] if all elements of [a] belong to [b]. Eager. + @since NEXT_RELEASE *) + +(*$T + subset (2 -- 4) (1 -- 4) + not (subset (1 -- 4) (2 -- 10)) +*) + val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t (** [unfoldr f b] will apply [f] to [b]. If it yields [Some (x,b')] then [x] is returned From 7cdebbc0f1ad352ecdc2cd996920febf65c534c1 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 17 Feb 2017 17:18:39 +0100 Subject: [PATCH 08/11] add toc to readme --- README.adoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.adoc b/README.adoc index ab9fc56..4987725 100644 --- a/README.adoc +++ b/README.adoc @@ -13,6 +13,8 @@ way of iterating on a finite number of values, only allocating (most of the time one intermediate closure to do so. For instance, iterating on keys, or values, of a `Hashtbl.t`, without creating a list. +toc::[] + == Documentation There is only one important type, `'a Sequence.t`, and lots of functions built From c5beeb3fb102bc0ae819e113445a45e621bf9b76 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 17 Feb 2017 17:21:09 +0100 Subject: [PATCH 09/11] typo --- README.adoc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index 4987725..311414b 100644 --- a/README.adoc +++ b/README.adoc @@ -95,7 +95,6 @@ underlying hash function): - : int = 11 (* now to get the values *) -# Sequence.of_t # Sequence.of_hashtbl h |> Sequence.map snd |> Sequence.to_list;; - : string list = ["6"; "2"; "8"; "7"; "3"; "5"; "4"; "9"; "0"; "10"; "1"] ---- @@ -122,7 +121,7 @@ use `Sequence.(--) : int -> int -> int Sequence.t`. NOTE: with **flambda** under sufficiently strong optimization flags, such compositions of operators -will be compiled to an actual loop with no overhead! +should be compiled to an actual loop with no overhead! === Iterating on sub-trees From d68c80f51d063c7f52c3ce80744189d7c75bb829 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 17 Feb 2017 17:24:48 +0100 Subject: [PATCH 10/11] update changelog --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3915aef..8f336ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog + +## 0.9 + +- distinction between `diagonal,diagonal_l` +- add `init,fold_map,fold_filter_map,sorted,diagonal,findi,…` +- fix a few typos +- update readme: convert into asciidoc, add tutorial +- remove deprecated functions, add missing links to `SequenceLabels` + +## 0.8 + +- loop based implementation for `int_range_by` +- move files to 'src/', use qtest for tests +- add `int_range_by` +- add `Sequence.flat_map_l` + ## 0.7 - add missing entry in changelog and missing since annotations From 76191b85773f37ef72fde689ba2c5d45f6d8ac52 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 17 Feb 2017 17:25:24 +0100 Subject: [PATCH 11/11] prepare for 0.10 --- CHANGELOG.md | 8 ++++++++ README.adoc | 1 + _oasis | 2 +- opam | 2 +- src/Sequence.mli | 24 ++++++++++++------------ src/sequenceLabels.mli | 2 +- 6 files changed, 24 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f336ee..cf96d4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.10 + +- add `{union,inter,diff,subset}` +- add `{join_by,join_all_by,group_join_by}` +- add `find_map{,i}` as better alias to existing functions +- add `{max_exn,min_exn}` +- add `count` +- add `doc` and `test` to opam ## 0.9 diff --git a/README.adoc b/README.adoc index 311414b..719d098 100644 --- a/README.adoc +++ b/README.adoc @@ -169,6 +169,7 @@ enumerating the ways we can insert an element in a list. [source,OCaml] ---- +# open Sequence.Infix;; # module S = Sequence ;; # let rec insert x l = match l with | [] -> S.return [x] diff --git a/_oasis b/_oasis index eb4824c..ce827cf 100644 --- a/_oasis +++ b/_oasis @@ -1,6 +1,6 @@ OASISFormat: 0.4 Name: sequence -Version: 0.9 +Version: 0.10 Homepage: https://github.com/c-cube/sequence Authors: Simon Cruanes License: BSD-2-clause diff --git a/opam b/opam index 4081978..9f3cdf6 100644 --- a/opam +++ b/opam @@ -1,6 +1,6 @@ opam-version: "1.2" name: "sequence" -version: "0.9" +version: "0.10" author: "Simon Cruanes" maintainer: "simon.cruanes@inria.fr" license: "BSD-2-clauses" diff --git a/src/Sequence.mli b/src/Sequence.mli index fb16c81..f7f367a 100644 --- a/src/Sequence.mli +++ b/src/Sequence.mli @@ -149,7 +149,7 @@ val find : ('a -> 'b option) -> 'a t -> 'b option val find_map : ('a -> 'b option) -> 'a t -> 'b option (** Alias to {!find} - @since NEXT_RELEASE *) + @since 0.10 *) val findi : (int -> 'a -> 'b option) -> 'a t -> 'b option (** Indexed version of {!find} @@ -157,7 +157,7 @@ val findi : (int -> 'a -> 'b option) -> 'a t -> 'b option val find_mapi : (int -> 'a -> 'b option) -> 'a t -> 'b option (** Alias to {!findi} - @since NEXT_RELEASE *) + @since 0.10 *) val find_pred : ('a -> bool) -> 'a t -> 'a option (** [find_pred p l] finds the first element of [l] that satisfies [p], @@ -256,7 +256,7 @@ val count : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) -> 'a t -> ('a * int) t (** Map each distinct element to its number of occurrences in the whole seq. Similar to [group_by seq |> map (fun l->List.hd l, List.length l)] - @since NEXT_RELEASE *) + @since 0.10 *) val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t (** Remove consecutive duplicate elements. Basically this is @@ -300,7 +300,7 @@ val join_by : ?eq:'key equal -> ?hash:'key hash -> values [(x,y)] from [(a,b)] with the same [key] using [merge]. If [merge] returns [None], the combination of values is discarded. - @since NEXT_RELEASE *) + @since 0.10 *) val join_all_by : ?eq:'key equal -> ?hash:'key hash -> ('a -> 'key) -> ('b -> 'key) -> @@ -317,7 +317,7 @@ val join_all_by : ?eq:'key equal -> ?hash:'key hash -> - call [merge k l1 l2]. If [merge] returns [None], the combination of values is discarded, otherwise it returns [Some c] and [c] is inserted in the result. - @since NEXT_RELEASE *) + @since 0.10 *) val group_join_by : ?eq:'a equal -> ?hash:'a hash -> ('b -> 'a) -> @@ -329,14 +329,14 @@ val group_join_by : ?eq:'a equal -> ?hash:'a hash -> sequence such that [eq x (key y)]. Elements of the first sequences without corresponding values in the second one are mapped to [[]] - @since NEXT_RELEASE *) + @since 0.10 *) val inter : ?eq:'a equal -> ?hash:'a hash -> 'a t -> 'a t -> 'a t (** Intersection of two collections. Each element will occur at most once in the result. Eager. - @since NEXT_RELEASE *) + @since 0.10 *) (*$= [2;4;5;6] (inter (1--6) (cons 2 (4--10)) |> sort |> to_list) @@ -348,7 +348,7 @@ val union : 'a t -> 'a t -> 'a t (** Union of two collections. Each element will occur at most once in the result. Eager. - @since NEXT_RELEASE *) + @since 0.10 *) (*$= [2;4;5;6] (union (4--6) (cons 2 (4--5)) |> sort |> to_list) @@ -358,7 +358,7 @@ val diff : ?eq:'a equal -> ?hash:'a hash -> 'a t -> 'a t -> 'a t (** Set difference. Eager. - @since NEXT_RELEASE *) + @since 0.10 *) (*$= [1;2;8;9;10] (diff (1--10) (3--7) |> to_list) @@ -368,7 +368,7 @@ val subset : ?eq:'a equal -> ?hash:'a hash -> 'a t -> 'a t -> bool (** [subset a b] returns [true] if all elements of [a] belong to [b]. Eager. - @since NEXT_RELEASE *) + @since 0.10 *) (*$T subset (2 -- 4) (1 -- 4) @@ -391,7 +391,7 @@ val max : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option val max_exn : ?lt:('a -> 'a -> bool) -> 'a t -> 'a (** Unsafe version of {!max} @raise Not_found if the sequence is empty - @since NEXT_RELEASE *) + @since 0.10 *) val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option (** Min element of the sequence, using the given comparison function. @@ -400,7 +400,7 @@ val min : ?lt:('a -> 'a -> bool) -> 'a t -> 'a option val min_exn : ?lt:('a -> 'a -> bool) -> 'a t -> 'a (** Unsafe version of {!min} @raise Not_found if the sequence is empty - @since NEXT_RELEASE *) + @since 0.10 *) val head : 'a t -> 'a option (** First element, if any, otherwise [None] diff --git a/src/sequenceLabels.mli b/src/sequenceLabels.mli index 2829be4..b28e492 100644 --- a/src/sequenceLabels.mli +++ b/src/sequenceLabels.mli @@ -216,7 +216,7 @@ val count : ?hash:('a -> int) -> ?eq:('a -> 'a -> bool) -> 'a t -> ('a * int) t (** Map each distinct element to its number of occurrences in the whole seq. Similar to [group_by seq |> map (fun l->List.hd l, List.length l)] - @since NEXT_RELEASE *) + @since 0.10 *) val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t (** Remove consecutive duplicate elements. Basically this is