doc: migrate readme back to markdown

This commit is contained in:
Simon Cruanes 2018-12-13 18:58:06 -06:00
parent 6a8197d0f8
commit 5cfc83ddde

View file

@ -1,6 +1,4 @@
= Iter # Iter
:toc: macro
:source-highlighter: pygments
Simple abstraction over `iter` functions, intended to iterate efficiently Simple abstraction over `iter` functions, intended to iterate efficiently
on collections while performing some transformations. Used to be called `Sequence`. on collections while performing some transformations. Used to be called `Sequence`.
@ -13,49 +11,44 @@ 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, one intermediate closure to do so. For instance, iterating on keys, or values,
of a `Hashtbl.t`, without creating a list. of a `Hashtbl.t`, without creating a list.
image::https://travis-ci.org/c-cube/iter.svg?branch=master[alt="Build Status", link="https://travis-ci.org/c-cube/iter"] [![build status](https://travis-ci.org/c-cube/iter.svg?branch=master)](https://travis-ci.org/c-cube/iter)
toc::[] ## Documentation
== Documentation
There is only one important type, `'a Iter.t`, and lots of functions built There is only one important type, `'a Iter.t`, and lots of functions built
around this type. around this type.
To get an overview of iter (originally "sequence"), its origins and why it was created, To get an overview of iter (originally "sequence"), its origins and why it was created,
you can start with http://simon.cedeela.fr/assets/talks/sequence.pdf[the slides of a talk] you can start with [the slides of a talk](http://simon.cedeela.fr/assets/talks/sequence.pdf)
I (@c-cube) made at some OCaml meeting. I (@c-cube) made at some OCaml meeting.
See https://c-cube.github.io/iter/[the online API] See [the online API](https://c-cube.github.io/iter/)
for more details on the set of available functions. for more details on the set of available functions.
== Build ## Build
1. via opam `opam install iter` 1. via opam `opam install iter`
2. manually (need OCaml >= 4.02.0): `make all install` 2. manually (need OCaml >= 4.02.0): `make all install`
If you have https://github.com/vincent-hugot/iTeML[qtest] installed, If you have [qtest](https://github.com/vincent-hugot/qtest) installed,
you can build and run tests with you can build and run tests with
---- ```
$ ./configure --enable-tests
$ make test $ make test
---- ```
If you have https://github.com/Chris00/ocaml-benchmark[benchmarks] installed, If you have [benchmarks](https://github.com/Chris00/ocaml-benchmark) installed,
you can build and run benchmarks with you can build and run benchmarks with
---- ```
$ make benchs $ make benchs
$ ./benchs.native ```
----
To see how to use the library, check the `examples` directory. To see how to use the library, check the following tutorial.
`tests.ml` has a few examples of how to convert basic data structures into The `tests` and `examples` directories also have some examples, but they're a bit arcane.
iterators, and conversely.
== Short Tutorial ## Short Tutorial
=== Transferring Data ### Transferring Data
Conversion between n container types Conversion between n container types
would take n² functions. In practice, for a given collection would take n² functions. In practice, for a given collection
@ -63,8 +56,8 @@ we can at best hope for `to_list` and `of_list`.
With iter, if the source structure provides a With iter, if the source structure provides a
`iter` function (or a `to_iter` wrapper), it becomes: `iter` function (or a `to_iter` wrapper), it becomes:
[source,OCaml] ```ocaml
---- # #use "src/Iter.ml";;
# let q = Queue.create();; # let q = Queue.create();;
# Iter.( 1 -- 10 |> to_queue q);; # Iter.( 1 -- 10 |> to_queue q);;
- : unit = () - : unit = ()
@ -76,7 +69,7 @@ With iter, if the source structure provides a
- : unit = () - : unit = ()
# Iter.of_stack s |> Iter.to_list ;; # Iter.of_stack s |> Iter.to_list ;;
- : int list = [10; 9; 8; 7; 6; 5; 4; 3; 2; 1] - : int list = [10; 9; 8; 7; 6; 5; 4; 3; 2; 1]
---- ```
Note how the list of elements is reversed when we transfer them Note how the list of elements is reversed when we transfer them
from the queue to the stack. from the queue to the stack.
@ -85,8 +78,7 @@ Another example is extracting the list of values of
a hashtable (in an undefined order that depends on the a hashtable (in an undefined order that depends on the
underlying hash function): underlying hash function):
[source,OCaml] ```ocaml
----
# let h = Hashtbl.create 16;; # let h = Hashtbl.create 16;;
# for i = 0 to 10 do # for i = 0 to 10 do
Hashtbl.add h i (string_of_int i) Hashtbl.add h i (string_of_int i)
@ -99,16 +91,15 @@ underlying hash function):
(* now to get the values *) (* now to get the values *)
# Iter.of_hashtbl h |> Iter.map snd |> Iter.to_list;; # Iter.of_hashtbl h |> Iter.map snd |> Iter.to_list;;
- : string list = ["6"; "2"; "8"; "7"; "3"; "5"; "4"; "9"; "0"; "10"; "1"] - : string list = ["6"; "2"; "8"; "7"; "3"; "5"; "4"; "9"; "0"; "10"; "1"]
---- ```
=== Replacing `for` loops ### Replacing `for` loops
The `for` loop is a bit limited, and lacks compositionality. The `for` loop is a bit limited, and lacks compositionality.
Instead, it can be more convenient and readable to Instead, it can be more convenient and readable to
use `Iter.(--) : int -> int -> int Iter.t`. use `Iter.(--) : int -> int -> int Iter.t`.
[source,OCaml] ```ocaml
----
# Iter.(1 -- 10_000_000 |> fold (+) 0);; # Iter.(1 -- 10_000_000 |> fold (+) 0);;
- : int = 50000005000000 - : int = 50000005000000
@ -119,18 +110,17 @@ use `Iter.(--) : int -> int -> int Iter.t`.
|> fold (+) 0 |> fold (+) 0
);; );;
- : int = 8345837500 - : int = 8345837500
---- ```
NOTE: with **flambda** under sufficiently strong **NOTE**: with _flambda_ under sufficiently strong
optimization flags, such compositions of operators optimization flags, such compositions of operators
should be compiled to an actual loop with no overhead! should be compiled to an actual loop with no overhead!
=== Iterating on sub-trees ### Iterating on sub-trees
A small λ-calculus AST, and some operations on it. A small λ-calculus AST, and some operations on it.
[source,OCaml] ```ocaml
----
# type term = # type term =
| Var of string | Var of string
| App of term * term | App of term * term
@ -159,9 +149,9 @@ val size : term -> int = <fun >
# let vars_list l = Iter.(of_list l |> flat_map vars);; # let vars_list l = Iter.(of_list l |> flat_map vars);;
val vars_list : term list -> string sequence = <fun > val vars_list : term list -> string sequence = <fun >
---- ```
=== Permutations ### Permutations
Makes it easy to write backtracking code (a non-deterministic Makes it easy to write backtracking code (a non-deterministic
function returning several `'a` function returning several `'a`
@ -169,8 +159,7 @@ will just return a `'a Iter.t`).
Here, we generate all permutations of a list by Here, we generate all permutations of a list by
enumerating the ways we can insert an element in a list. enumerating the ways we can insert an element in a list.
[source,OCaml] ```ocaml
----
# open Iter.Infix;; # open Iter.Infix;;
# module S = Iter ;; # module S = Iter ;;
# let rec insert x l = match l with # let rec insert x l = match l with
@ -186,37 +175,35 @@ enumerating the ways we can insert an element in a list.
# permute [1;2;3;4] |> S.take 2 |> S.to_list ;; # permute [1;2;3;4] |> S.take 2 |> S.to_list ;;
- : int list list = [[4; 3; 2; 1]; [4; 3; 1; 2]] - : int list list = [[4; 3; 2; 1]; [4; 3; 1; 2]]
```
---- ### Advanced example
=== Advanced example
The module `examples/sexpr.mli` exposes the interface of the S-expression The module `examples/sexpr.mli` exposes the interface of the S-expression
example library. It requires OCaml>=4.0 to compile, because of the GADT example library. It requires OCaml>=4.0 to compile, because of the GADT
structure used in the monadic parser combinators part of `examples/sexpr.ml`. structure used in the monadic parser combinators part of `examples/sexpr.ml`.
Be careful that this is quite obscure. Be careful that this is quite obscure.
== Comparison with https://github.com/c-cube/gen[gen] ## Comparison with [gen](https://github.com/c-cube/gen)
- `Gen` is an *external* iterator. - `Gen` is an *external* iterator.
It means that the code which consumes It means that the code which consumes
some iterator of type `'a Gen.t` is the one which decides when to some iterator of type `'a Gen.t` is the one which decides when to
go to the next element. This gives a lot of flexibility, for example go to the next element. This gives a lot of flexibility, for example
when iterating on several iterators at the same time: when iterating on several iterators at the same time:
+
[source,OCaml] ```ocaml
---- let zip (g1: 'a Gen.t) (g2:'b Gen.t) : ('a * 'b) Gen.t =
let zip (g1: 'a Gen.t) (g2:'b Gen.t) : ('a * 'b) Gen.t = let x1 = ref (g1 ()) in
let x1 = ref (g1 ()) in let x2 = ref (g2 ()) in
let x2 = ref (g2 ()) in fun () -> match !x1, !x2 with
fun () -> match !x1, !x2 with | None, _ | _, None -> None
| None, _ | _, None -> None | Some x, Some y ->
| Some x, Some y -> (* fetch next elements from g1 and g2 *)
(* fetch next elements from g1 and g2 *) x1 := g1 ();
x1 := g1 (); x2 := g2 ();
x2 := g2 (); Some (x,y)
Some (x,y) ```
----
- `Iter` is an *internal* iterator. When one wishes to iterate over - `Iter` is an *internal* iterator. When one wishes to iterate over
an `'a Iter.t`, one has to give a callback `f : 'a -> unit` an `'a Iter.t`, one has to give a callback `f : 'a -> unit`
@ -237,6 +224,6 @@ becomes a if test).
For more details, you can read http://gallium.inria.fr/blog/generators-iterators-control-and-continuations/ . For more details, you can read http://gallium.inria.fr/blog/generators-iterators-control-and-continuations/ .
== License ## License
Iter is available under the BSD license. Iter is available under the BSD license.