From 59cb2d3922d39725588641756741383bf5a18cd4 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 22 Apr 2016 23:17:58 +0200 Subject: [PATCH 01/21] update opam --- opam | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opam b/opam index f51a13c0..751f23b0 100644 --- a/opam +++ b/opam @@ -26,13 +26,13 @@ remove: [ ] depends: [ "ocamlfind" {build} + "oasis" {build} "base-bytes" "result" "cppo" {build} - "oasis" {build} "ocamlbuild" {build} ] -depopts: [ "sequence" "base-bigarray" "base-unix" "base-threads" ] +depopts: [ "sequence" "base-bigarray" "base-unix" "base-threads" "qtest" { test } ] conflicts: [ "sequence" { < "0.5" } "qtest" { < "2.2" } From e6abec05d7859cf597f4e27b6f8493349b085767 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 22 Apr 2016 23:47:43 +0200 Subject: [PATCH 02/21] link to doc of 0.17 --- README.adoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.adoc b/README.adoc index 8787436d..19f3dd6e 100644 --- a/README.adoc +++ b/README.adoc @@ -268,3 +268,6 @@ A few guidelines: Powered by image:http://oasis.forge.ocamlcore.org/oasis-badge.png[alt="OASIS", style="border: none;", link="http://oasis.forge.ocamlcore.org/"] +== Documentation by version + +- http://c-cube.github.io/ocaml-containers/0.17/[0.17] From 4b7897ec827fbe83d5b4accb90d30f3831bc238c Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Sun, 24 Apr 2016 18:15:24 +0200 Subject: [PATCH 03/21] doc --- src/core/CCFormat.mli | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/CCFormat.mli b/src/core/CCFormat.mli index 45d4aafb..7d2fd22b 100644 --- a/src/core/CCFormat.mli +++ b/src/core/CCFormat.mli @@ -37,6 +37,9 @@ val arrayi : ?start:string -> ?stop:string -> ?sep:string -> val seq : ?start:string -> ?stop:string -> ?sep:string -> 'a printer -> 'a sequence printer val opt : 'a printer -> 'a option printer +(** [opt pp] prints options as follows: + [Some x] will become "some foo" if [pp x ---> "foo"] + [None] will become "none" *) (** In the tuple printers, the [sep] argument is only available @since 0.17 *) From c800a23a27f276574a29519df2685feddb8e3c0d Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Sun, 24 Apr 2016 23:11:12 +0200 Subject: [PATCH 04/21] some doc --- doc/intro.txt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/doc/intro.txt b/doc/intro.txt index 6e69309d..b4b2bd73 100644 --- a/doc/intro.txt +++ b/doc/intro.txt @@ -22,6 +22,8 @@ by ocamlfind). {4 Core Modules (extension of the standard library)} +{b findlib name}: containers + {!modules: CCArray CCBool @@ -63,6 +65,8 @@ such as: {4 Containers.data} +{b findlib name}: containers.data + Various data structures. {!modules: @@ -123,6 +127,8 @@ CCLazy_list} {4 String} +{b findlib name}: containers.string + {!modules: CCApp_parse CCKMP @@ -139,6 +145,8 @@ Use bigarrays to hold large strings and map files directly into memory. {4 Advanced} +{b findlib name}: containers.advanced + This module is qualified with [Containers_advanced]. It requires {{:https://github.com/c-cube/sequence} Sequence}. @@ -152,7 +160,11 @@ Moved to its own repository. Moved to its own repository -{4 Others} +{4 Thread Helpers} + +{b findlib name}: containers.thread + +Modules related to the use of [Thread]. {!modules: CCBlockingQueue From fb97af680b92d83f675a28ef5a263c828b61525b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Glen=20M=C3=A9vel?= Date: Mon, 25 Apr 2016 00:56:05 +0200 Subject: [PATCH 05/21] add CCList.range_by --- src/core/CCList.ml | 20 ++++++++++++++++++++ src/core/CCList.mli | 7 +++++++ 2 files changed, 27 insertions(+) diff --git a/src/core/CCList.ml b/src/core/CCList.ml index 857512ce..975a0861 100644 --- a/src/core/CCList.ml +++ b/src/core/CCList.ml @@ -792,6 +792,26 @@ module Idx = struct *) end +let range_by ~step i j = + if step = 0 then raise (Invalid_argument "CCList.range_by"); + let rec up i j acc = + if i>j then acc else up i (j-step) (j::acc) + and down i j acc = + if i 0 then up i j [] else down i j [] + +(*$T + range_by ~step:1 0 0 = [0] + range_by ~step:1 5 0 = [] + range_by ~step:2 0 4 = [0;2;4] + range_by ~step:2 0 5 = [0;2;4] + range_by ~step:~-1 0 5 = [] + range_by ~step:~-2 5 1 = [5;3;1] + range_by ~step:~-2 5 0 = [5;3;1] +*) + let range i j = let rec up i j acc = if i=j then i::acc else up i (j-1) (j::acc) diff --git a/src/core/CCList.mli b/src/core/CCList.mli index 41f4e5d0..8bb1ba7e 100644 --- a/src/core/CCList.mli +++ b/src/core/CCList.mli @@ -275,6 +275,13 @@ end (** {2 Other Constructors} *) +val range_by : step:int -> int -> int -> int t +(** [range_by ~step i j] iterates on integers from [i] to [j] included, + where the difference between successive elements is [step]. + use a negative [step] for a decreasing list. + @raise Invalid_argument if [step=0] + @since NEXT_RELEASE *) + val range : int -> int -> int t (** [range i j] iterates on integers from [i] to [j] included . It works both for decreasing and increasing ranges *) From f57d7267ac54ac6f942a74c6da78d034b9f013ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Glen=20M=C3=A9vel?= Date: Mon, 25 Apr 2016 11:39:03 +0200 Subject: [PATCH 06/21] bug fix for CCList.range_by --- src/core/CCList.ml | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/core/CCList.ml b/src/core/CCList.ml index 975a0861..80b8578f 100644 --- a/src/core/CCList.ml +++ b/src/core/CCList.ml @@ -793,23 +793,29 @@ module Idx = struct end let range_by ~step i j = - if step = 0 then raise (Invalid_argument "CCList.range_by"); - let rec up i j acc = - if i>j then acc else up i (j-step) (j::acc) - and down i j acc = - if i 0 then up i j [] else down i j [] + if step = 0 then + raise (Invalid_argument "CCList.range_by") + else if (if step > 0 then i>j else i Date: Mon, 25 Apr 2016 11:51:38 +0200 Subject: [PATCH 07/21] add test --- src/core/CCList.ml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/core/CCList.ml b/src/core/CCList.ml index 80b8578f..92c2747d 100644 --- a/src/core/CCList.ml +++ b/src/core/CCList.ml @@ -818,6 +818,12 @@ let range_by ~step i j = range_by ~step:max_int 0 2 = [0] *) +(*$Q + Q.(pair small_int small_int) (fun (i,j) -> \ + let i = min i j and j = max i j in \ + range_by ~step:1 i j = range i j) +*) + let range i j = let rec up i j acc = if i=j then i::acc else up i (j-1) (j::acc) From 24add9d4f76df3d29c175a62dae7efee488fe00f Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Mon, 25 Apr 2016 11:56:07 +0200 Subject: [PATCH 08/21] make a test less slow --- src/data/CCTrie.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/CCTrie.ml b/src/data/CCTrie.ml index 7af7a165..569b6bdc 100644 --- a/src/data/CCTrie.ml +++ b/src/data/CCTrie.ml @@ -368,7 +368,7 @@ module Make(W : WORD) *) (*$Q - Q.(pair (list (pair printable_string int)) printable_string) (fun (l,s) -> \ + Q.(pair (list (pair (printable_string_of_size Gen.(0 -- 30)) int)) printable_string) (fun (l,s) -> \ let m = String.of_list l in \ let s' = String.longest_prefix s m in \ CCString.prefix ~pre:s' s) From 560cba975425ecd67786e812dccf33c446d81490 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Mon, 25 Apr 2016 19:52:57 +0200 Subject: [PATCH 09/21] add `Lazy_list.filter` --- src/iter/CCLazy_list.ml | 12 ++++++++++++ src/iter/CCLazy_list.mli | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/src/iter/CCLazy_list.ml b/src/iter/CCLazy_list.ml index ffaf76ce..a1d94cf0 100644 --- a/src/iter/CCLazy_list.ml +++ b/src/iter/CCLazy_list.ml @@ -40,6 +40,18 @@ let rec map ~f l = | lazy (Cons (x,tl)) -> Cons (f x, map ~f tl) ) +let filter ~f l = + let rec aux f l = match l with + | lazy Nil -> Nil + | lazy (Cons (x,tl)) when f x -> Cons (x, lazy (aux f tl)) + | lazy (Cons (_, tl)) -> aux f tl + in + lazy (aux f l) + +(*$= + [2;4;6] (of_list [1;2;3;4;5;6;7] |> filter ~f:(fun x -> x mod 2=0) |> to_list) +*) + let rec append a b = lazy ( match a with diff --git a/src/iter/CCLazy_list.mli b/src/iter/CCLazy_list.mli index 6a51cd3b..77c7870d 100644 --- a/src/iter/CCLazy_list.mli +++ b/src/iter/CCLazy_list.mli @@ -31,6 +31,10 @@ val head : 'a t -> ('a * 'a t) option val map : f:('a -> 'b) -> 'a t -> 'b t (** Lazy map *) +val filter : f:('a -> bool) -> 'a t -> 'a t +(** Filter values + @since NEXT_RELEASE *) + val append : 'a t -> 'a t -> 'a t (** Lazy concatenation *) From c3e0f81f7ebab9d3843dafd40f23de938494c73a Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Mon, 25 Apr 2016 20:39:08 +0200 Subject: [PATCH 10/21] add `CCLazy_list.take` --- src/iter/CCLazy_list.ml | 9 +++++++++ src/iter/CCLazy_list.mli | 6 +++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/iter/CCLazy_list.ml b/src/iter/CCLazy_list.ml index a1d94cf0..a258f372 100644 --- a/src/iter/CCLazy_list.ml +++ b/src/iter/CCLazy_list.ml @@ -50,8 +50,17 @@ let filter ~f l = (*$= [2;4;6] (of_list [1;2;3;4;5;6;7] |> filter ~f:(fun x -> x mod 2=0) |> to_list) + [2;4;6] (of_gen Gen.(1 -- max_int) |> filter ~f:(fun x -> x mod 2=0) |> take 3 |> to_list) *) +let rec take n l = + lazy ( + match l with + | _ when n=0 -> Nil + | lazy Nil -> Nil + | lazy (Cons (x,tl)) -> Cons (x, take (n-1) tl) + ) + let rec append a b = lazy ( match a with diff --git a/src/iter/CCLazy_list.mli b/src/iter/CCLazy_list.mli index 77c7870d..613be3fe 100644 --- a/src/iter/CCLazy_list.mli +++ b/src/iter/CCLazy_list.mli @@ -32,7 +32,11 @@ val map : f:('a -> 'b) -> 'a t -> 'b t (** Lazy map *) val filter : f:('a -> bool) -> 'a t -> 'a t -(** Filter values +(** Filter values. + @since NEXT_RELEASE *) + +val take : int -> 'a t -> 'a t +(** Take at most n values. @since NEXT_RELEASE *) val append : 'a t -> 'a t -> 'a t From 790e665441dc44bf52794a04bd3cbd9e447b4e26 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Tue, 26 Apr 2016 15:46:30 +0200 Subject: [PATCH 11/21] some howto for releases --- HOWTO.adoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/HOWTO.adoc b/HOWTO.adoc index 528d72e8..de85e04c 100644 --- a/HOWTO.adoc +++ b/HOWTO.adoc @@ -16,7 +16,8 @@ can be removed. 8. `git merge master` 9. `oasis setup; make test doc` 10. tag, and push both to github -11. new opam package +11. `opam pin https://github.com/c-cube/ocaml-containers#` +12. new opam package: `opam publish prepare; opam publish submit` == List Authors From 3190278d8643beaf97dd4eb5ad8c679202ef3f1e Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Wed, 4 May 2016 23:12:32 +0200 Subject: [PATCH 12/21] add aliases to deprecated functions from `String`, add `Fun.opaque_identity` --- src/core/CCFun.cppo.ml | 10 ++++++++++ src/core/CCFun.mli | 6 ++++++ src/core/CCString.cppo.ml | 20 ++++++++++++++++++++ src/core/CCString.mli | 18 ++++++++++++++++++ 4 files changed, 54 insertions(+) diff --git a/src/core/CCFun.cppo.ml b/src/core/CCFun.cppo.ml index c14cdb84..b8927c81 100644 --- a/src/core/CCFun.cppo.ml +++ b/src/core/CCFun.cppo.ml @@ -15,6 +15,16 @@ let (@@) f x = f x #endif +#if OCAML_MAJOR >= 4 && OCAML_MINOR >= 3 + +let opaque_identity = Sys.opaque_identity + +#else + +let opaque_identity x = x + +#endif + let compose f g x = g (f x) let compose_binop f g x y = g (f x) (f y) diff --git a/src/core/CCFun.mli b/src/core/CCFun.mli index 7d731708..6f8a1c0e 100644 --- a/src/core/CCFun.mli +++ b/src/core/CCFun.mli @@ -65,6 +65,12 @@ val finally2 : h:(unit -> _) -> ('a -> 'b -> 'c) -> 'a -> 'b -> 'c [h ()] is called whether [f x y] rose an exception or not. @since 0.16 *) +val opaque_identity : 'a -> 'a +(** [opaque_identity x] is like [x], but prevents Flambda from using [x]'s + definition for optimizing it (flambda is an optimization/inlining pass + in OCaml >= 4.03). + @since NEXT_RELEASE *) + (** {2 Monad} Functions with a fixed domain are monads in their codomain *) diff --git a/src/core/CCString.cppo.ml b/src/core/CCString.cppo.ml index b476f92f..8a510d4e 100644 --- a/src/core/CCString.cppo.ml +++ b/src/core/CCString.cppo.ml @@ -639,6 +639,26 @@ let exists2 p s1 s2 = try iter2 (fun c1 c2 -> if p c1 c2 then raise MyExit) s1 s2; false with MyExit -> true +(** {2 Ascii functions} *) + +#if OCAML_MAJOR >= 4 && OCAML_MINOR >= 3 + +let capitalize_ascii = String.capitalize_ascii +let uncapitalize_ascii = String.uncapitalize_ascii +let uppercase_ascii = String.uppercase_ascii +let lowercase_ascii = String.lowercase_ascii + +#else + +let capitalize_ascii = String.capitalize +let uncapitalize_ascii = String.uncapitalize +let uppercase_ascii = String.uppercase +let lowercase_ascii = String.lowercase + +#endif + + + let pp buf s = Buffer.add_char buf '"'; Buffer.add_string buf s; diff --git a/src/core/CCString.mli b/src/core/CCString.mli index a61d52fd..edee2895 100644 --- a/src/core/CCString.mli +++ b/src/core/CCString.mli @@ -378,6 +378,24 @@ val exists2 : (char -> char -> bool) -> string -> string -> bool @raise Invalid_argument if the strings have not the same length @since 0.12 *) +(** {2 Ascii functions} + + Those functions are deprecated in {!String} since 4.03, so we provide + a stable alias for them even in older versions *) + +val capitalize_ascii : string -> string +(** See {!String}. @since NEXT_RELEASE *) + +val uncapitalize_ascii : string -> string +(** See {!String}. @since NEXT_RELEASE *) + +val uppercase_ascii : string -> string +(** See {!String}. @since NEXT_RELEASE *) + +val lowercase_ascii : string -> string +(** See {!String}. @since NEXT_RELEASE *) + + (** {2 Splitting} *) module Split : sig From e08fc88e13d4b1215227b2de6245232787e92e7f Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Thu, 5 May 2016 18:16:23 +0200 Subject: [PATCH 13/21] add `CCGraph.is_dag` --- src/data/CCGraph.ml | 13 +++++++++++++ src/data/CCGraph.mli | 11 +++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/data/CCGraph.ml b/src/data/CCGraph.ml index 37a9da15..2155f089 100644 --- a/src/data/CCGraph.ml +++ b/src/data/CCGraph.ml @@ -43,6 +43,10 @@ module Seq = struct a (fun x -> acc := f !acc x); !acc let to_list seq = fold (fun acc x->x::acc) [] seq |> List.rev + exception Exit_ + let exists_ f seq = + try seq (fun x -> if f x then raise Exit_); false + with Exit_ -> true end (** {2 Interfaces for graphs} *) @@ -315,6 +319,15 @@ module Traverse = struct end end +(** {2 Cycles} *) + +let is_dag ?(tbl=mk_table 128) ~graph vs = + Traverse.Event.dfs ~tbl ~graph vs + |> Seq.exists_ + (function + | `Edge (_, `Back) -> true + | _ -> false) + (** {2 Topological Sort} *) exception Has_cycle diff --git a/src/data/CCGraph.mli b/src/data/CCGraph.mli index 22bc1233..36511313 100644 --- a/src/data/CCGraph.mli +++ b/src/data/CCGraph.mli @@ -224,6 +224,17 @@ module Traverse : sig end end +(** {2 Cycles} *) + +val is_dag : + ?tbl:'v set -> + graph:('v, _) t -> + 'v sequence -> + bool +(** [is_dag ~graph vs] returns [true] if the subset of [graph] reachable + from [vs] is acyclic. + @since NEXT_RELEASE *) + (** {2 Topological Sort} *) exception Has_cycle From 55cf10caf28959da5f53abc4603f7be48334eadb Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Mon, 16 May 2016 21:44:15 +0200 Subject: [PATCH 14/21] update README --- README.adoc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index 19f3dd6e..b0180351 100644 --- a/README.adoc +++ b/README.adoc @@ -2,10 +2,11 @@ :toc: macro :source-highlighter: pygments -image::media/logo.png[logo] - What is _containers_? (take a look at the link:TUTORIAL.adoc[tutorial]! or the http://cedeela.fr/~simon/software/containers[documentation]) +In `containers` and `containers.data`, all modules abide by +_pay for what you use_: only modules that are used are linked (there are no +cross-module dependencies). - A usable, reasonably well-designed library that extends OCaml's standard library (in 'src/core/', packaged under `containers` in ocamlfind. Modules @@ -42,6 +43,8 @@ image:https://ci.cedeela.fr/buildStatus/icon?job=containers[alt="Build Status", toc::[] +image::media/logo.png[logo] + == Change Log See link:CHANGELOG.adoc[this file]. From 22e07c5c5ebe1870ac415db7d795ebd61e9dd200 Mon Sep 17 00:00:00 2001 From: Fabian Date: Tue, 17 May 2016 22:33:47 +0200 Subject: [PATCH 15/21] Improve CCVector.equal --- src/core/CCVector.ml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/core/CCVector.ml b/src/core/CCVector.ml index d1290cf5..878adf4d 100644 --- a/src/core/CCVector.ml +++ b/src/core/CCVector.ml @@ -243,12 +243,22 @@ let append_list a b = match b with *) let equal eq v1 v2 = - let n = min v1.size v2.size in + v1.size == v2.size + && + let n = v1.size in let rec check i = if i = n - then v1.size = v2.size + then true else eq (get v1 i) (get v2 i) && check (i+1) - in check 0 + in + check 0 + +(*$T + equal (=) (create ()) (create ()) + equal (=) (return 42) (return 42) + not (equal (=) (create ()) (return 42)) + not (equal (=) (return 42) (create ())) +*) let compare cmp v1 v2 = let n = min v1.size v2.size in From 0a5e131ce1f7ea3f8d8baa1a0fafbcdca6b1cb4e Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Tue, 17 May 2016 23:23:45 +0200 Subject: [PATCH 16/21] use structural equality --- src/core/CCVector.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/CCVector.ml b/src/core/CCVector.ml index 878adf4d..480334e5 100644 --- a/src/core/CCVector.ml +++ b/src/core/CCVector.ml @@ -243,7 +243,7 @@ let append_list a b = match b with *) let equal eq v1 v2 = - v1.size == v2.size + v1.size = v2.size && let n = v1.size in let rec check i = From 4c998bf57ad1cb4ee5a7eb247f3aa1672b7418fe Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Fri, 20 May 2016 11:32:27 +0200 Subject: [PATCH 17/21] add `CCArray.get_safe` (close #70) --- src/core/CCArray.ml | 37 +++++++++++++++++++++++++++++++++++++ src/core/CCArray.mli | 4 ++++ 2 files changed, 41 insertions(+) diff --git a/src/core/CCArray.ml b/src/core/CCArray.ml index 848952a6..a5496aef 100644 --- a/src/core/CCArray.ml +++ b/src/core/CCArray.ml @@ -22,6 +22,10 @@ module type S = sig val get : 'a t -> int -> 'a + val get_safe : 'a t -> int -> 'a option + (** [get_safe a i] returns [Some a.(i)] if [i] is a valid index + @since NEXT_RELEASE *) + val set : 'a t -> int -> 'a -> unit val length : _ t -> int @@ -291,6 +295,21 @@ let length = Array.length let get = Array.get +let get_safe a i = + if i>=0 && i=a.j then invalid_arg "Array.Sub.get"; a.arr.(j) + let get_safe a i = + try Some (get a i) + with Invalid_argument _ -> None + + (*$inject + let sub_a = Sub.make [|1;2;3;4;5|] 1 ~len:3 + *) + + (*$= + (Some 2) (Sub.get_safe sub_a 0) + (Some 3) (Sub.get_safe sub_a 1) + (Some 4) (Sub.get_safe sub_a 2) + None (Sub.get_safe sub_a 4) + None (Sub.get_safe sub_a max_int) + None (Sub.get_safe sub_a ~-1) + None (Sub.get_safe sub_a ~-42) + *) + let set a i x = let j = a.i + i in if i<0 || j>=a.j then invalid_arg "Array.Sub.set"; diff --git a/src/core/CCArray.mli b/src/core/CCArray.mli index 29157eb7..b8b83b84 100644 --- a/src/core/CCArray.mli +++ b/src/core/CCArray.mli @@ -24,6 +24,10 @@ module type S = sig val get : 'a t -> int -> 'a + val get_safe : 'a t -> int -> 'a option + (** [get_safe a i] returns [Some a.(i)] if [i] is a valid index + @since NEXT_RELEASE *) + val set : 'a t -> int -> 'a -> unit val length : _ t -> int From cfad88e906a6aad188683a21f658d5fe6822e39a Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Tue, 14 Jun 2016 13:58:37 +0200 Subject: [PATCH 18/21] add `CCOpt.get_or` with label, deprecates `get` --- src/core/CCOpt.ml | 4 ++++ src/core/CCOpt.mli | 11 +++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/core/CCOpt.ml b/src/core/CCOpt.ml index b15d93d2..3413e18d 100644 --- a/src/core/CCOpt.ml +++ b/src/core/CCOpt.ml @@ -93,6 +93,10 @@ let get default x = match x with | None -> default | Some y -> y +let get_or ~default x = match x with + | None -> default + | Some y -> y + let get_exn = function | Some x -> x | None -> invalid_arg "CCOpt.get_exn" diff --git a/src/core/CCOpt.mli b/src/core/CCOpt.mli index feca2f3b..0214fa41 100644 --- a/src/core/CCOpt.mli +++ b/src/core/CCOpt.mli @@ -27,7 +27,7 @@ val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool val return : 'a -> 'a t -(** Monadic return *) +(** Monadic return, that is [return x = Some x] *) val (>|=) : 'a t -> ('a -> 'b) -> 'b t (** Infix version of {!map} *) @@ -62,7 +62,13 @@ val for_all : ('a -> bool) -> 'a t -> bool val get : 'a -> 'a t -> 'a (** [get default x] unwraps [x], but if [x = None] it returns [default] instead. - @since 0.4.1 *) + @since 0.4.1 + @deprecated use {!get_or} @since NEXT_RELEASE *) + +val get_or : default:'a -> 'a t -> 'a +(** [get_or ~default o] extracts the value from [o], or + returns [default] if [o = None]. + @since NEXT_RELEASE *) val get_exn : 'a t -> 'a (** Open the option, possibly failing if it is [None] @@ -103,6 +109,7 @@ val (<+>) : 'a t -> 'a t -> 'a t val choice : 'a t list -> 'a t (** [choice] returns the first non-[None] element of the list, or [None] *) + (** {2 Infix Operators} @since 0.16 *) From 6639cb8e774827a32d8fbe269a5743701fcbe722 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Tue, 14 Jun 2016 14:07:30 +0200 Subject: [PATCH 19/21] update implem of `CCVector.equal`; add a random test --- src/core/CCVector.ml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/core/CCVector.ml b/src/core/CCVector.ml index 480334e5..40296609 100644 --- a/src/core/CCVector.ml +++ b/src/core/CCVector.ml @@ -247,9 +247,7 @@ let equal eq v1 v2 = && let n = v1.size in let rec check i = - if i = n - then true - else eq (get v1 i) (get v2 i) && check (i+1) + i = n || (eq (get v1 i) (get v2 i) && check (i+1)) in check 0 @@ -260,6 +258,11 @@ let equal eq v1 v2 = not (equal (=) (return 42) (create ())) *) +(*$Q + Q.(let g = list_of_size Gen.(0--10) small_int in pair g g) (fun (l1,l2) -> \ + equal (=) (of_list l1) (of_list l2) = (l1=l2)) +*) + let compare cmp v1 v2 = let n = min v1.size v2.size in let rec check i = From 590d4108e83dcaa0db08407cb7c8a0d5ce435b28 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Tue, 14 Jun 2016 14:10:05 +0200 Subject: [PATCH 20/21] comment --- _oasis | 2 +- src/advanced/CCLinq.mli | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/_oasis b/_oasis index 39957f0a..5038b5f5 100644 --- a/_oasis +++ b/_oasis @@ -40,7 +40,7 @@ Flag "bigarray" Default: true Flag "advanced" - Description: Build advanced combinators, including CCLinq (requires "sequence") + Description: Build advanced combinators (requires "sequence") Default: true Library "containers" diff --git a/src/advanced/CCLinq.mli b/src/advanced/CCLinq.mli index 898eea54..02136979 100644 --- a/src/advanced/CCLinq.mli +++ b/src/advanced/CCLinq.mli @@ -33,7 +33,7 @@ Functions and operations are assumed to be referentially transparent, i.e. they should not rely on external side effects, they should not rely on the order of execution. -@deprecated use {{: https://github.com/c-cube/olinq} OLinq} (once released) +@deprecated use {{: https://github.com/c-cube/olinq} OLinq} {[ From 228011d9aa799caeb73964f52a410abcb71e03b4 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Tue, 14 Jun 2016 14:12:02 +0200 Subject: [PATCH 21/21] prepare for 0.18 --- CHANGELOG.adoc | 13 ++++++++++++- _oasis | 2 +- src/core/CCArray.ml | 2 +- src/core/CCArray.mli | 2 +- src/core/CCFun.mli | 2 +- src/core/CCList.mli | 2 +- src/core/CCOpt.mli | 4 ++-- src/core/CCString.mli | 8 ++++---- src/data/CCGraph.mli | 2 +- src/iter/CCLazy_list.mli | 4 ++-- 10 files changed, 26 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 0afdf806..677e85ba 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,8 +1,19 @@ = Changelog +== 0.18 + +- update implem of `CCVector.equal` +- add `CCOpt.get_or` with label, deprecates `get` +- add `CCArray.get_safe` (close #70) +- add `CCGraph.is_dag` +- add aliases to deprecated functions from `String`, add `Fun.opaque_identity` +- add `CCLazy_list.take` +- add `Lazy_list.filter` +- add CCList.range_by + == 0.17 -=== potentially breaking +=== potentially breaking - change the semantics of `CCString.find_all` (allow overlaps) diff --git a/_oasis b/_oasis index 5038b5f5..c89760dd 100644 --- a/_oasis +++ b/_oasis @@ -1,6 +1,6 @@ OASISFormat: 0.4 Name: containers -Version: 0.17 +Version: 0.18 Homepage: https://github.com/c-cube/ocaml-containers Authors: Simon Cruanes License: BSD-2-clause diff --git a/src/core/CCArray.ml b/src/core/CCArray.ml index a5496aef..a7230a77 100644 --- a/src/core/CCArray.ml +++ b/src/core/CCArray.ml @@ -24,7 +24,7 @@ module type S = sig val get_safe : 'a t -> int -> 'a option (** [get_safe a i] returns [Some a.(i)] if [i] is a valid index - @since NEXT_RELEASE *) + @since 0.18 *) val set : 'a t -> int -> 'a -> unit diff --git a/src/core/CCArray.mli b/src/core/CCArray.mli index b8b83b84..eb6b9d29 100644 --- a/src/core/CCArray.mli +++ b/src/core/CCArray.mli @@ -26,7 +26,7 @@ module type S = sig val get_safe : 'a t -> int -> 'a option (** [get_safe a i] returns [Some a.(i)] if [i] is a valid index - @since NEXT_RELEASE *) + @since 0.18 *) val set : 'a t -> int -> 'a -> unit diff --git a/src/core/CCFun.mli b/src/core/CCFun.mli index 6f8a1c0e..8ff1f20d 100644 --- a/src/core/CCFun.mli +++ b/src/core/CCFun.mli @@ -69,7 +69,7 @@ val opaque_identity : 'a -> 'a (** [opaque_identity x] is like [x], but prevents Flambda from using [x]'s definition for optimizing it (flambda is an optimization/inlining pass in OCaml >= 4.03). - @since NEXT_RELEASE *) + @since 0.18 *) (** {2 Monad} diff --git a/src/core/CCList.mli b/src/core/CCList.mli index 8bb1ba7e..a3a35b26 100644 --- a/src/core/CCList.mli +++ b/src/core/CCList.mli @@ -280,7 +280,7 @@ val range_by : step:int -> int -> int -> int t where the difference between successive elements is [step]. use a negative [step] for a decreasing list. @raise Invalid_argument if [step=0] - @since NEXT_RELEASE *) + @since 0.18 *) val range : int -> int -> int t (** [range i j] iterates on integers from [i] to [j] included . It works diff --git a/src/core/CCOpt.mli b/src/core/CCOpt.mli index 0214fa41..cb2242ba 100644 --- a/src/core/CCOpt.mli +++ b/src/core/CCOpt.mli @@ -63,12 +63,12 @@ val for_all : ('a -> bool) -> 'a t -> bool val get : 'a -> 'a t -> 'a (** [get default x] unwraps [x], but if [x = None] it returns [default] instead. @since 0.4.1 - @deprecated use {!get_or} @since NEXT_RELEASE *) + @deprecated use {!get_or} @since 0.18 *) val get_or : default:'a -> 'a t -> 'a (** [get_or ~default o] extracts the value from [o], or returns [default] if [o = None]. - @since NEXT_RELEASE *) + @since 0.18 *) val get_exn : 'a t -> 'a (** Open the option, possibly failing if it is [None] diff --git a/src/core/CCString.mli b/src/core/CCString.mli index edee2895..4d292fd1 100644 --- a/src/core/CCString.mli +++ b/src/core/CCString.mli @@ -384,16 +384,16 @@ val exists2 : (char -> char -> bool) -> string -> string -> bool a stable alias for them even in older versions *) val capitalize_ascii : string -> string -(** See {!String}. @since NEXT_RELEASE *) +(** See {!String}. @since 0.18 *) val uncapitalize_ascii : string -> string -(** See {!String}. @since NEXT_RELEASE *) +(** See {!String}. @since 0.18 *) val uppercase_ascii : string -> string -(** See {!String}. @since NEXT_RELEASE *) +(** See {!String}. @since 0.18 *) val lowercase_ascii : string -> string -(** See {!String}. @since NEXT_RELEASE *) +(** See {!String}. @since 0.18 *) (** {2 Splitting} *) diff --git a/src/data/CCGraph.mli b/src/data/CCGraph.mli index 36511313..5ccb00f2 100644 --- a/src/data/CCGraph.mli +++ b/src/data/CCGraph.mli @@ -233,7 +233,7 @@ val is_dag : bool (** [is_dag ~graph vs] returns [true] if the subset of [graph] reachable from [vs] is acyclic. - @since NEXT_RELEASE *) + @since 0.18 *) (** {2 Topological Sort} *) diff --git a/src/iter/CCLazy_list.mli b/src/iter/CCLazy_list.mli index 613be3fe..3f046fb2 100644 --- a/src/iter/CCLazy_list.mli +++ b/src/iter/CCLazy_list.mli @@ -33,11 +33,11 @@ val map : f:('a -> 'b) -> 'a t -> 'b t val filter : f:('a -> bool) -> 'a t -> 'a t (** Filter values. - @since NEXT_RELEASE *) + @since 0.18 *) val take : int -> 'a t -> 'a t (** Take at most n values. - @since NEXT_RELEASE *) + @since 0.18 *) val append : 'a t -> 'a t -> 'a t (** Lazy concatenation *)