• Stars
    star
    104
  • Rank 320,299 (Top 7 %)
  • Language
    OCaml
  • License
    BSD 2-Clause "Sim...
  • Created over 11 years ago
  • Updated 10 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Simple iterator abstract datatype, intended to iterate efficiently on collections while performing some transformations.

Iter build

Clean and efficient loop fusion for all your iterating needs!

# #require "iter";;
# let p x = x mod 5 = 0 in
  Iter.(1 -- 5_000 |> filter p |> map (fun x -> x * x) |> fold (+) 0);;
- : int = 8345837500

Iter is a simple abstraction over iter functions intended to iterate efficiently on collections while performing some transformations. Common operations supported by Iter include filter, map, take, drop, append, flat_map, etc. Iter is not designed to be as general-purpose or flexible as Seq. Rather, it aims at providing a very simple and efficient 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. Similarly, the code above is turned into a single optimized for loop with flambda.

Documentation

There is only one important type, 'a Iter.t, and lots of functions built around this type. See the online API for more details on the set of available functions. Some examples can be found below.

The library used to be called Sequence. Some historical perspective is provided in this talk given by @c-cube at some OCaml meeting.

Short Tutorial

Transferring Data

Conversion between n container types would take nยฒ functions. In practice, for a given collection we can at best hope for to_list and of_list. With iter, if the source structure provides a iter function (or a to_iter wrapper), it becomes:

# let q : int Queue.t = Queue.create();;
val q : int Queue.t = <abstr>
# Iter.( 1 -- 10 |> to_queue q);;
- : unit = ()
# Iter.of_queue q |> Iter.to_list ;;
- : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]

# let s : int Stack.t = Stack.create();;
val s : int Stack.t = <abstr>
# Iter.(of_queue q |> to_stack s);;
- : unit = ()
# Iter.of_stack s |> Iter.to_list ;;
- : int list = [10; 9; 8; 7; 6; 5; 4; 3; 2; 1]

Note how the list of elements is reversed when we transfer them from the queue to the stack.

Another example is extracting the list of values of a hashtable (in an undefined order that depends on the underlying hash function):

# let h: (int, string) Hashtbl.t = Hashtbl.create 16;;
val h : (int, string) Hashtbl.t = <abstr>
# for i = 0 to 10 do
     Hashtbl.add h i (string_of_int i)
  done;;
- : unit = ()

# Hashtbl.length h;;
- : int = 11

# (* now to get the values *)
  Iter.of_hashtbl h |> Iter.map snd |> Iter.to_list;;
- : string list = ["6"; "2"; "8"; "7"; "3"; "5"; "4"; "9"; "0"; "10"; "1"]

Replacing for loops

The for loop is a bit limited, and lacks compositionality. Instead, it can be more convenient and readable to use Iter.(--) : int -> int -> int Iter.t.

# Iter.(1 -- 10_000_000 |> fold (+) 0);;
- : int = 50000005000000

# let p x = x mod 5 = 0 in
  Iter.(1 -- 5_000
    |> filter p
    |> map (fun x -> x * x)
    |> fold (+) 0
  );;
- : int = 8345837500

NOTE: with flambda under sufficiently strong optimization flags, such compositions of operators should be compiled to an actual loop with no overhead!

Iterating on sub-trees

A small ฮป-calculus AST, and some operations on it.

# type term =
  | Var of string
  | App of term * term
  | Lambda of term ;;
type term = Var of string | App of term * term | Lambda of term

# let rec subterms : term -> term Iter.t =
  fun t ->
    let open Iter.Infix in
    Iter.cons t
      (match t with
      | Var _ -> Iter.empty
      | Lambda u -> subterms u
      | App (a,b) ->
        Iter.append (subterms a) (subterms b))
  ;;
val subterms : term -> term Iter.t = <fun>

# (* Now we can define many other functions easily! *)
  let vars t =
    Iter.filter_map
      (function Var s -> Some s | _ -> None)
      (subterms t) ;;
val vars : term -> string Iter.t = <fun>

# let size t = Iter.length (subterms t) ;;
val size : term -> int = <fun>

# let vars_list l = Iter.(of_list l |> flat_map vars);;
val vars_list : term list -> string Iter.t = <fun>

Permutations

Makes it easy to write backtracking code (a non-deterministic function returning several 'a will just return a 'a Iter.t). Here, we generate all permutations of a list by enumerating the ways we can insert an element in a list.

# open Iter.Infix;;
# let rec insert x l = match l with
  | [] -> Iter.return [x]
  | y :: tl ->
    Iter.append
      (insert x tl >|= fun tl' -> y :: tl')
      (Iter.return (x :: l)) ;;
val insert : 'a -> 'a list -> 'a list Iter.t = <fun>

# let rec permute l = match l with
  | [] -> Iter.return []
  | x :: tl -> permute tl >>= insert x ;;
val permute : 'a list -> 'a list Iter.t = <fun>

# permute [1;2;3;4] |> Iter.take 2 |> Iter.to_list ;;
- : int list list = [[4; 3; 2; 1]; [4; 3; 1; 2]]

Advanced example

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 structure used in the monadic parser combinators part of examples/sexpr.ml. Be careful that this is quite obscure.

Comparison with Seq from the standard library, and with Gen

  • Seq is an external iterator. It means that the code which consumes some iterator of type 'a Seq.t is the one which decides when to go to the next element. This gives a lot of flexibility, for example when iterating on several iterators at the same time:

    let rec zip a b () = match a(), b() with
      | Nil, _
      | _, Nil -> Nil
      | Cons (x, a'), Cons (y, b') -> Cons ((x,y), zip a' b')
  • Iter is an internal iterator. When one wishes to iterate over an 'a Iter.t, one has to give a callback f : 'a -> unit that is called in succession over every element of the iterator. Control is not handed back to the caller before the whole iteration is over. This makes zip impossible to implement. However, the type 'a Iter.t is general enough that it can be extracted from any classic iter function, including from data structures such as Map.S.t or Set.S.t or Hashtbl.t; one cannot obtain a 'a Seq.t from these without having access to the internal data structure.

  • Gen (from the gen library) is an external iterator, like Seq, but it is imperative, mutable, and consumable (you can't iterate twice on the same 'a Gen.t). It looks a lot like iterators in rust/java/โ€ฆ and can be pretty efficient in some cases. Since you control iteration you can also write map2, for_all2, etc but only with linear use of input generators (since you can traverse them only once). That requires some trickery for cartesian_product (like storing already produced elements internally).

In short, 'a Seq.t is more expressive than 'a Iter.t, but it also requires more knowledge of the underlying source of items. For some operations such as map or flat_map, Iter is also extremely efficient and will, if flambda permits, be totally removed at compile time (e.g. Iter.(--) becomes a for loop, and Iter.filter becomes a if test).

For more details, you can read http://gallium.inria.fr/blog/generators-iterators-control-and-continuations/ or see the slides about Iter by me (c-cube) when Iter was still called Sequence.

Build

  1. via opam opam install iter
  2. manually (need OCaml >= 4.02.0): make all install

If you have qtest installed, you can build and run tests with

$ make test

If you have benchmarks installed, you can build and run benchmarks with

$ make benchs

To see how to use the library, check the following tutorial. The tests and examples directories also have some examples, but they're a bit arcane.

License

Iter is available under the BSD license.

More Repositories

1

ocaml-containers

A lightweight, modular standard library extension, string library, and interfaces to various libraries (unix, threads, etc.) BSD license.
OCaml
474
star
2

qcheck

QuickCheck inspired property-based testing for OCaml.
OCaml
330
star
3

datalog

An in-memory datalog implementation for OCaml.
Prolog
247
star
4

printbox

print nested boxes, lists, arrays, tables in several formats
OCaml
75
star
5

tiny_httpd

Minimal HTTP server using good old threads + blocking IO, with a small request router.
OCaml
73
star
6

stimsym

[toy] A rewriting language similar to the core of Mathematica
OCaml
54
star
7

gen

Simple, efficient iterators for OCaml
OCaml
53
star
8

moonpool

Commodity thread pools and concurrency primitives for OCaml 5
OCaml
52
star
9

mc2

[research] A modular SMT solver in OCaml, based on mcSAT
SMT
39
star
10

oseq

Purely functional iterators compatible with standard `seq`.
OCaml
32
star
11

lwt-pipe

[beta] A multi-consumer, multi-producers blocking queue and stream for Lwt
OCaml
31
star
12

batsat

A (parametrized) Rust SAT solver originally based on MiniSat
Rust
30
star
13

calculon

Library for writing IRC bots in OCaml, a collection of plugins, and a dramatic robotic actor.
OCaml
28
star
14

cconv

[dead] combinators for type conversion (serialization/deserialization) to/from several formats. See this blog post (outdated): http://cedeela.fr/universal-serialization-and-deserialization.html
OCaml
27
star
15

ezcurl

A simple wrapper around OCurl.
OCaml
26
star
16

linol

Wrapper around the OCaml `lsp` library to make it easier to write LSP servers
OCaml
25
star
17

bare-ocaml

runtime library and code-generator for BARE (https://baremessages.org/)
OCaml
24
star
18

sidekick

A modular library for CDCL(T) SMT solvers, with [wip] proof generation.
SMT
24
star
19

ocaml-iostream

generic I/O streams of bytes
OCaml
24
star
20

smbc

Experimental model finder/SMT solver for functional programming.
OCaml
22
star
21

choice

Choice operator in OCaml, providing a backtracking monad
OCaml
22
star
22

spelll

fuzzy string searching, using Levenshtein automaton. Can be used for spell-checking.
OCaml
22
star
23

ocaml-avro

Runtime library and schema compiler for the Avro serialization format
OCaml
20
star
24

ocaml-trace

Common interface for tracing/instrumentation libraries in OCaml
OCaml
18
star
25

sqlite3_utils

[beta] High-level wrapper around ocaml-sqlite3
OCaml
18
star
26

olinq

LINQ-like combinators for manipulating collections of in-memory data
OCaml
17
star
27

maki

[beta] persistent memoization of computations, e.g. for repeatable tests and benchmarks
OCaml
17
star
28

ocaml-bigstring

Overlay over bigarrays of chars
OCaml
15
star
29

thread-local-storage

thread-local storage for OCaml
OCaml
15
star
30

fuseau

[alpha] lightweight fiber library for OCaml 5
OCaml
13
star
31

ocaml-minisat

OCaml bindings to Minisat
C++
13
star
32

ocaml-gnuplot

bindings to gnuplot (fork of https://bitbucket.org/ogu/gnuplot-ocaml/)
OCaml
13
star
33

seq

compatibility package for the standard OCaml iterator type
OCaml
12
star
34

quip

[wip] Proof format and checker for first-order and higher-order theorem provers
OCaml
12
star
35

batsat-ocaml

OCaml bindings for batsat (https://github.com/c-cube/batsat)
OCaml
11
star
36

trustee

[wip] A LCF-style kernel of trust intended for certified ATP and proof checking for FOL/HOL.
OCaml
11
star
37

ocabot

IRC bot for #ocaml@freenode
OCaml
10
star
38

ocaml-qbf

OCaml bindings to QBF solver(s)
C
10
star
39

jsonrpc2

[unfinished] Jsonrpc2 for OCaml, parametrized by the underlying IO.
OCaml
10
star
40

IKSML

[toy] industrial-strength implementation of the SKI calculus, using XML
8
star
41

thrifty

[wip] Reimplementation of thrift in OCaml
Thrift
8
star
42

hashset_benchs

Reproducing https://www.reddit.com/r/rust/comments/4dd5yl/rust_vs_f_hashset_benchmark/
Clojure
8
star
43

funarith

[wip] functorial library with classic algorithms for arithmetic
OCaml
8
star
44

ocaml-atomic

Compatibility package for the Atomic module
OCaml
8
star
45

indexed-set

OCaml implementation of indexed sets (inspired from Haskell's ixSet library)
OCaml
8
star
46

ty

[draft] dynamic representation of types
OCaml
7
star
47

zulip-log-viewer

Small website to serve zulip logs obtained from [zulip archive](https://github.com/zulip/zulip-archive)
OCaml
6
star
48

ocaml-twirp

[wip] OCaml implementation of Twirp using ocaml-protoc
OCaml
6
star
49

poc-modular-io

proof of concept for https://github.com/ocaml/RFCs/pull/19
OCaml
6
star
50

frog-utils

[frozen] Scheduling and running jobs on a shared computer, then analyse their output
OCaml
5
star
51

oasis-parser

Simple parser for _oasis files
OCaml
5
star
52

ocaml-chord

[unfinished] Chord DHT implementation in OCaml (not production-ready)
OCaml
5
star
53

rcontext

Per-request context, inspired from Go's
OCaml
5
star
54

space_camels

[toy] Tiny game built to try notty
OCaml
5
star
55

smtlib-utils

A parser and some utils for SMTLIB. For a fully compliant parser, see https://github.com/Gbury/dolmen/.
SMT
5
star
56

gemini-client

[toy] ocaml client for gemini
OCaml
4
star
57

containers-lwt

Utilities for Lwt
OCaml
4
star
58

bender

[toy] IRC bot in rust, for my private use
Rust
4
star
59

vim-tptp

Vim syntax file for the TPTP logic format (http://www.cs.miami.edu/~tptp/)
Vim Script
4
star
60

iterators_bench

[bench] benchmark of various iterator implementations
OCaml
4
star
61

playground

various little experiments
OCaml
4
star
62

ccbor

[WIP] CBOR codec for OCaml
OCaml
4
star
63

containers-misc

[toy] Random stuff from containers, low quality, experimental
OCaml
4
star
64

ocaml-ty

[clone] Fork of ocaml-ty by Grรฉgoire Henry (original url https://gitorious.org/ocaml-ty/)
OCaml
4
star
65

neperien

[unfinished] structured, hierarchical log system for OCaml
OCaml
4
star
66

andes

[toy, wip] A chain with lots of lemmas. More specifically, a logic programming engine.
OCaml
4
star
67

paradox

[clone] model finder for first-order logic, from http://vlsicad.eecs.umich.edu/BK/Slots/cache/www.cs.chalmers.se/~koen/paradox/
Haskell
4
star
68

logtk

[migrated to https://github.com/c-cube/zipperposition] Logic toolkit, designed primarily for first-order automated reasoning. It aims at providing basic types and algorithms (terms, unification, orderings, indexing, etc.) that can be factored out of several applications.
OCaml
4
star
69

ldl

[TOY] loop-dee-loop, an event loop
OCaml
3
star
70

bencode_rpc

[toy] Remote Procedure Call with B-encode serialization and Lwt concurrency (probably not production ready).
OCaml
3
star
71

bender-ocaml

[dead] Write OCaml plugins for bender
OCaml
3
star
72

quip-book

Book for Quip, a proof format for first-order and higher-order theorem provers
SMT
3
star
73

ocaml-aig

[toy] And-Inverter Graph in OCaml
OCaml
2
star
74

tiny-httpd-moonpool-bench

experiment with tiny_httpd using moonpool as a scheduler
Makefile
2
star
75

tomato-chan

[wip] IRC bot.
OCaml
2
star
76

unif-visitor

Playground for visitors on terms
OCaml
2
star
77

microsat

experiments around microsat
Rust
1
star
78

ocaml-polynomials

[toy] Toy implementation of multi-variable polynomials over Z
OCaml
1
star
79

ppx_deriving_cconv

[deprecated] ppx_deriving instance for CConv encoders/decoders
OCaml
1
star
80

tip-parser

[obsolete] parser for https://github.com/tip-org/
OCaml
1
star
81

ocaml-irclog

parsing IRC logs as produced by irssi
OCaml
1
star
82

irky

[wip] IRC client for OCaml
OCaml
1
star
83

strictly_tally

Implementation of relative placement tabulation for dance competitions
Rust
1
star