# package ppx_seq

# Sequence Literals for your OCaml

`ppx_seq`

is a lightweight syntax rewriter that hopes to make dealing with functional iterators as pain-free as possible. It does so by giving users:

- Literals
- Ranges (WIP)
- Patterns (WIP)
- Notes on side-effects

The rewriter's surface area is so incredibly small that this document alone should be enough to cover it all. Here's how to use it:

### Literals

Seq literals can be used wherever an expression is expected. The syntax for them takes the general form `[%seq ...]`

.

#### Empty literal

`[%seq] => fun () -> Seq.Nil`

The empty sequence, which may also be expressed as `Seq.empty`

NOTE: an older syntax was also used to express the empty sequence: `[%seq.empty]`

, but it's no longer supported.

#### Occupied literal

`[%seq 1; 2; 3] => fun () -> Seq.Cons(1, fun () -> Seq.Cons(2, ...))`

This is the original syntax that motivated the creation of `ppx_seq`

, every value in the sequence is properly delayed inside a thunk.

### Ranges

Similar to Literals, can be used whenever an expression is expected. However, their payload is evaluated *eagerly*. See: Notes on side-effects (this may change in a future release).

+============================================================================+ | IMPORTANT | | | | Ranges rely on the following definitions being in scope: | | - compare | | - succ | | - (+), (-) | | | | This could be useful for overriding behaviour, but may lead to bugs if not | | handled with care. | | (this may change in a future release). | +============================================================================+

If you're familiar with Haskell, this range syntax follows closely its `enumFrom[Then|To][To]`

sugar. As a reminder, that sugar has four forms:

`[a,b..]`

and its special form`[a..]`

`[a,b..c]`

and its special form`[a..c]`

However, unlike Haskell, the default behaviour of this range syntax is **not** to allow infinite ranges to be constructed from the third and fourth "bounded" forms.

If you're not familiar with Haskell, the semantics will be explained below.

#### Infinite

Infinite ranges are specified using `[%seq.inf ...]`

.

First form:

`[%seq.inf a, b]`

is equivalent to

`let a = a and s = b - a in [%seq a; s + a; s + s + a; ...]`

Second form:

`[%seq.inf a]`

is similar, but replace `(s + _)`

with `(succ _)`

So it's equivalent to:

`let a = a in [%seq a; succ a; succ (succ a); ...]`

#### Finite

(WIP)

Finite ranges are specified using `[%seq.fin ...]`

.

First form:

`[%seq.fin a, b, c]`

is equivalent to

```
let a = a and s = b - a and c = c in
[%seq a; s + a; s + s + a; ...; f]
(* where f = n * s + a and f <= c *)
```

NOTE: there are checks performed to make sure an infinite sequence is not produced:

- if
`a`

and`c`

are equal, no steps are taken, and we get a singleton seq. - if
`a`

and`b`

are equal,`a`

and`c`

are not, this would produce an infinite sequence, which is not allowed, so we return an empty seq.

Second form:

`[%seq.fin a, b]`

is similar, but replace `(s + _)`

with:

`(succ _)`

when`b`

is greater than`a`

`(pred _)`

when`b`

is less than`a`

### Patterns

TODO

### Notes on side-effects

`[%seq ...]`

Literals are just a normal `Seq`

as we've seen above, which means they also do recomputations on traversal for side-effectful expressions.

```
let x = ref 0 in
let s = [%seq incr x] in
let a = !x in
let b =
Seq.iter ignore s;
Seq.iter ignore s;
!x
in
a, b
=> - : int * int = (0, 2)
```

Meanwhile, `[%seq.fin ...]`

and `[%seq.inf ...]`

Ranges are generated by evaluating their payload, so every subexpression in the payload will be evaluated one-per-range.

```
let r = ref 0 in
let s = [%seq.inf (incr r; 1)] in
let _ = s() in
let a = !r in
let _ = [%seq.inf (incr r; 1), (incr r; 2)] in
let b = !r in
a, b
=> - : int * int = (1, 3)
```

Notice that we don't really "force/use" the second sequence anywhere up there.

for more info or examples see the tests on `<ppx_seq_repo>/test/..`

.