From 6674f5750b7fa13e2a28c748950fa637b1289932 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Wed, 24 Feb 2016 21:21:52 +0100 Subject: [PATCH] add a tutorial file --- .gitignore | 1 + README.adoc | 4 +- TUTORIAL.adoc | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 TUTORIAL.adoc diff --git a/.gitignore b/.gitignore index 8f50b9ea..8d2ffd6d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ TAGS *.docdir setup.* qtest* +*.html diff --git a/README.adoc b/README.adoc index 26cbce77..175483da 100644 --- a/README.adoc +++ b/README.adoc @@ -4,7 +4,7 @@ image::media/logo.png[logo] -What is _containers_? +What is _containers_? (take a look at the link:TUTORIAL.adoc[tutorial]!) - A usable, reasonably well-designed library that extends OCaml's standard library (in 'src/core/', packaged under `containers` in ocamlfind. Modules @@ -55,6 +55,8 @@ See link:CHANGELOG.adoc[this file]. == Use +Start with the link:TUTORIAL.adoc[tutorial] + You can either build and install the library (see <>), or just copy files to your own project. The last solution has the benefits that you don't have additional dependencies nor build complications (and it may enable diff --git a/TUTORIAL.adoc b/TUTORIAL.adoc new file mode 100644 index 00000000..205a0153 --- /dev/null +++ b/TUTORIAL.adoc @@ -0,0 +1,175 @@ += Tutorial +:source-highlighter: pygments + +This tutorial contains a few examples to illustrate the features and +usage of containers. We assume containers is installed and that +the library is loaded, e.g. with: + +[source,OCaml] +---- +#require "containers";; +---- + +We will start with a few list helpers, then look at other parts of +the library, including printers, maps, etc. + +[source,OCaml] +---- + +(* quick reminder of this awesome standard operator *) +# (|>) ;; +- : 'a -> ('a -> 'b) -> 'b = + +# open CCList.Infix;; + +# let l = 1 -- 100;; +val l : int list = [1; 2; .....] + +# l + |> CCList.filter_map + (fun x-> if x mod 3=0 then Some (float x) else None) + |> CCList.take 5 ;; +- : float list = [3.; 6.; 9.; 12.; 15.] + +# let l2 = l |> CCList.take_while (fun x -> x<10) ;; +val l2 : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9] + +(* an extension of Map.Make, compatible with Map.Make(CCInt) *) +# module IntMap = CCMap.Make(CCInt);; + +(* conversions using the "sequence" type, fast iterators that are + pervasively used in containers. Combinators can be found + in the opam library "sequence". *) +# let map = + l2 + |> List.map (fun x -> x, string_of_int x) + |> CCList.to_seq + |> IntMap.of_seq;; +val map : string CCIntMap.t = + +(* check the type *) +# CCList.to_seq ;; +- : 'a list -> 'a sequence = +# IntMap.of_seq ;; +- : (int * 'a) CCMap.sequence -> 'a IntMap.t = + +(* we can print, too *) +# Format.printf "@[<2>map =@ @[%a@]@]@." + (IntMap.print CCFormat.int CCFormat.string_quoted) + map;; +map = + [1 --> "1", 2 --> "2", 3 --> "3", 4 --> "4", 5 --> "5", 6 --> "6", + 7 --> "7", 8 --> "8", 9 --> "9"] +- : unit = () + +(* options are good *) +# IntMap.get 3 map |> CCOpt.map (fun s->s ^ s);; +- : string option = Some "33" + +---- + +== New types: `CCVector`, `CCHeap`, `CCError`, `CCResult` + +Containers also contains (!) a few datatypes that are not from the standard +library but that are useful in a lot of situations: + +CCVector:: + A resizable array, with a mutability parameter. A value of type + `('a, CCVector.ro) CCVector.t` is an immutable vector of values of type `'a`, + whereas a `('a, CCVector.rw) CCVector.t` is a mutable vector that + can be modified. This way, vectors can be used in a quite functional + way, using operations such as `map` or `flat_map`, or in a more + imperative way. +CCHeap:: + A priority queue (currently, leftist heaps) functorized over + a module `sig val t val leq : t -> t -> bool` that provides a type `t` + and a partial order `leq` on `t`. +CCError:: + An error type for making error handling more explicit (an error monad, + really, if you're not afraid of the "M"-word). It is similar to the + more recent `CCResult`, but works with polymorphic variants for + compatibility with the numerous libraries that use the same type, + that is, `type ('a, 'b) CCError.t = [`Ok of 'a | `Error of 'b]`. +CCResult:: + It uses the new `result` type from the standard library (or from + the retrocompatibility package on opam), and presents an interface + similar to `CCError`. In an indeterminate amount of time, it will + totally replace `CCError`. + +Now for a few examples: + +[source,OCaml] +---- + +(* create a new empty vector. It is mutable, for otherwise it would + not be very useful. *) +# CCVector.create;; +- : unit -> ('a, CCVector.rw) CCVector.t = + +(* init, similar to Array.init, can be used to produce a + vector that is mutable OR immutable (see the 'mut parameter?) *) +# CCVector.init ;; +- : int -> (int -> 'a) -> ('a, 'mut) CCVector.t = c + +(* use the infix (--) operator for creating a range. Notice + that v is a vector of integer but its mutability is not + decided yet. *) +# let v = CCVector.(1 -- 10);; +val v : (int, '_a) CCVector.t = + +# Format.printf "v = @[%a@]@." (CCVector.print CCInt.print) v;; +v = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + +(* now let's mutate v *) +# CCVector.push v 42;; +- : unit = () + +(* now v is a mutable vector *) +# v;; +- : (int, CCVector.rw) CCVector.t = + +(* functional combinators! *) +# let v2 = v + |> CCVector.map (fun x-> x+1) + |> CCVector.filter (fun x-> x mod 2=0) + |> CCVector.rev ;; +val v2 : (int, '_a) CCVector.t = + +# Format.printf "v2 = @[%a@]@." (CCVector.print CCInt.print) v2;; +v2 = [10, 8, 6, 4, 2] + +(* let's transfer to a heap *) +# module IntHeap = CCHeap.Make(struct type t = int let leq = (<=) end);; + +# let h = v2 |> CCVector.to_seq |> IntHeap.of_seq ;; +val h : IntHeap.t = + +(* We can print the content of h + (printing is not necessarily in order, though) *) +# Format.printf "h = [@[%a@]]@." (IntHeap.print CCInt.print) h;; +h = [2,4,6,8,10] + +(* we can remove the first element, which also returns a new heap + that does not contain it — CCHeap is a functional data structure *) +# IntHeap.take h;; +- : (IntHeap.t * int) option = Some (, 2) + +# let h', x = IntHeap.take_exn h ;; +val h' : IntHeap.t = +val x : int = 2 + +(* see, 2 is removed *) +# IntHeap.to_list h' ;; +- : int list = [4; 6; 8; 10] + +---- + +=== To go further: containers.data + +There is also a sub-library called `containers.data`, with lots of +more specialized data-structures. +The documentation contains the API for all the modules +(see link:README.adoc[the readme]); they also provide +interface to `sequence` and, as the rest of containers, minimize +dependencies over other modules. +