# \[ANN\] ppx\_seq v0.1.1

**URL:** <https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227>\
**Category:** Community\
**Tags:** ppx, opam, announce\
**Created:** [January 27, 2022, 2:53am UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227 "2022-01-27T02:53:04Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![hyphenrf](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hyphenrf/32/2733_2.png) [@hyphenrf](https://discuss.ocaml.org/u/hyphenrf)\
**Post date:** [January 27, 2022, 2:53am UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/1 "2022-01-27T02:53:05Z")

</div>

Hello everyone, my first contribution to opam-repository has just been merged and is waiting to hit the caches of [opam.ocaml.org](https://opam.ocaml.org).

[ppx\_seq](https://github.com/hyphenrf/ppx_seq) is a cute un-intrusive literal syntax for `Seq`. The rewriter is simple and has very small surface area: just `[%seq x; y; z; ...]` and `[%seq.empty]`.  
It tries to be maximally compatible with all OCaml releases from 4.07 (when `Seq` was introduced) to 4.14 and beyond

The reason I created this rewriter is to make it an easier choice to reach first for `Seq` as a general data structure (instead of e.g. list). That wasn’t quite attractive before because of how minimal the `Seq` module was, it was mostly used as an intermediate step between two types of collections, but now with 4.14 about to be released, `Seq` is becoming a first-class data structure with a very versatile API.

I hope my little rewriter helps make it even more attractive to use. Check it out and maybe leave me some feedback. Thanks \<3

---

<div class="post-metadata">

**Author:** ![c-cube](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/c-cube/32/1727_2.png) [@c-cube](https://discuss.ocaml.org/u/c-cube)\
**Post date:** [January 29, 2022, 3:02am UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/2 "2022-01-29T03:02:35Z")

</div>

That’s a nice idea! A few remarks:

- you should commit the opam file, so people can `opam pin` your repository.
- markdown is nice for readme files 🙂
- you can be compatible with pre-4.07 versions of OCaml, by simple requiring the generate code to depend on the compatibility package `seq`.
- it’d be nice (but maybe harder) to implement basic comprehensions for sequences. I’m not sure what a OCaml-compatible syntax would be, though.

---

<div class="post-metadata">

**Author:** ![silene](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/silene/32/2707_2.png) [@silene](https://discuss.ocaml.org/u/silene)\
**Post date:** [January 29, 2022, 7:25am UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/3 "2022-01-29T07:25:29Z")

</div>

The documentation should make it clearer what the semantics is. You have chosen to translate `[%seq a; b]` to

```ocaml
fun () -> Seq.cons (a, fun () -> Seq.cons (b, fun () -> Seq.nil))

```

but some users might have expected it to be translated to

```ocaml
let a = a in let b = b in
fun () -> Seq.cons (a, fun () -> Seq.cons (b, fun () -> Seq.nil))

```

This matters a lot for side effects.

---

<div class="post-metadata">

**Author:** ![hyphenrf](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hyphenrf/32/2733_2.png) [@hyphenrf](https://discuss.ocaml.org/u/hyphenrf)\
**Post date:** [January 29, 2022, 4:23pm UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/4 "2022-01-29T16:23:31Z")

</div>

If I understand you correctly, your suggestion is that I should better clarify that side-effectful code gets properly delayed, right?  
That way people don’t expect side-effectful code to fire before being `Seq`’d like here in that first line…

> [@silene](#):
>
> but some users might have expected it to be translated to
> 
> ```auto
> let a = a in let b = b in
> fun () -> Seq.cons (a, fun () -> Seq.cons (b, fun () -> Seq.nil))
> 
> ```

(i.e. for [this test](https://git.sr.ht/~hyphens/ppx_seq/tree/master/item/test/ppx_seq.ml#L14-19) to fail)?

The rewritten output is indeed `fun () -> Seq.Cons (a, ...)`. The wrapping under `fun () -> ...` would prevent any side-effects from firing and I imagine that this is the intended behaviour of `Seq`. I might’ve assumed too much by thinking being implicit about that wouldn’t cause uncertainty. Thanks!

---

<div class="post-metadata">

**Author:** ![hyphenrf](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hyphenrf/32/2733_2.png) [@hyphenrf](https://discuss.ocaml.org/u/hyphenrf)\
**Post date:** [January 29, 2022, 4:44pm UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/5 "2022-01-29T16:44:10Z")

</div>

Compatibility has increased to OCaml 4.04.2, now only bounded by `ppxlib` itself.  
However, I made `seq` a test-only dependency to give people more freedom to override with their own custom `Seq` module without having to have `seq` around in the dependency list… Although I admit that’d be such a niche setup.

Still not sure about whether allowing such overriding is a good or bad thing too. Only time and tickets will tell haha

as for comprehensions, I believe that is covered with the more general `letop` syntax, and I’d rather keep it like that instead of rolling my own. It doesn’t sound too hard (I have some thoughts… maybe I can (ab)use the record syntax to get a nice comprehensions dsl…) but it feels like it isn’t within the domain of the rewriter… what do you think?

Something I’m more interested in is a [range syntax](https://github.com/hyphenrf/ppx_seq/issues/2) though. e.g. `[%seq a..b]` and `[%seq a, b..c]`

---

<div class="post-metadata">

**Author:** ![hyphenrf](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hyphenrf/32/2733_2.png) [@hyphenrf](https://discuss.ocaml.org/u/hyphenrf)\
**Post date:** [January 29, 2022, 5:07pm UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/6 "2022-01-29T17:07:51Z")

</div>

Also! there appears to be a package called `ppx_monadic` that does exactly those comprehensions. It’s not maintained anymore though (at least it seems so).

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [February 1, 2022, 1:13pm UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/7 "2022-02-01T13:13:18Z")

</div>

It would be interesting to extend this PPX to support pattern matching on `Seq.t` values, in the style of the old Stream parsers, see [parsers](https://camlp5.github.io/doc/htmlc/parsers.html).

Cheers,  
Nicolas

---

<div class="post-metadata">

**Author:** ![silene](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/silene/32/2707_2.png) [@silene](https://discuss.ocaml.org/u/silene)\
**Post date:** [February 2, 2022, 7:54am UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/8 "2022-02-02T07:54:37Z")

</div>

> [@hyphenrf](#):
>
> If I understand you correctly, your suggestion is that I should better clarify that side-effectful code gets properly delayed, right?

Yes. But saying that the side effects are delayed is not sufficient. There are basically three different semantics, and they all make sense. `[%seq a; b; ...]` could be any of the following:

1. `List.to_seq [a; b; ...]`, that is, side effects are performed eagerly and only once.
2. `Seq.map Lazy.force (List.to_seq [lazy a; lazy b; ...])`, that is, side effects are performed on demand, but only once.
3. `Seq.map (fun f -> f ()) (List.to_seq [fun () -> a; fun () -> b; ...])`, that is, side effects are performed on demand, but repeatedly.

---

<div class="post-metadata">

**Author:** ![hyphenrf](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hyphenrf/32/2733_2.png) [@hyphenrf](https://discuss.ocaml.org/u/hyphenrf)\
**Post date:** [February 3, 2022, 2:16pm UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/9 "2022-02-03T14:16:42Z")

</div>

Thanks for pointing that out, I made that point that it’s just plain `Seq` without any memoization or eager evaluation clear.

---

<div class="post-metadata">

**Author:** ![hyphenrf](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hyphenrf/32/2733_2.png) [@hyphenrf](https://discuss.ocaml.org/u/hyphenrf)\
**Post date:** [February 3, 2022, 2:17pm UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/10 "2022-02-03T14:17:19Z")

</div>

Excellent suggestion, I’ve been thinking about that yesterday actually!

---

<div class="post-metadata">

**Author:** ![Chet\_Murthy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chet_murthy/32/1501_2.png) [@Chet\_Murthy](https://discuss.ocaml.org/u/Chet_Murthy)\
**Post date:** [February 8, 2022, 7:11am UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/11 "2022-02-08T07:11:08Z")

</div>

@nojb , are you suggesting that it might be useful to port the stream-parsers to work on Seq.t ? B/c that’s probably not very difficult to do. Indeed, it would suffice to just make a wrapper module (call it “SeqStream”) that had the same API as what the stream-parsers use – which is pretty minimal.

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [February 8, 2022, 7:37am UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/12 "2022-02-08T07:37:32Z")

</div>

> [@Chet\_Murthy](#):
>
> @nojb , are you suggesting that it might be useful to port the stream-parsers to work on Seq.t ?

Well, that would be an orthogonal project. What I was suggesting is to have a lightweight ppx _syntax_ for seq/stream parsers which does not depend on `camlp{4,5}`. That syntax was convenient for writing recursive descent parsers, but depending on `camlp{4,5}` for this is overkill.

Cheers,  
Nicolas

---

<div class="post-metadata">

**Author:** ![vrotaru](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/vrotaru/32/39_2.png) [@vrotaru](https://discuss.ocaml.org/u/vrotaru)\
**Post date:** [February 8, 2022, 8:54am UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/13 "2022-02-08T08:54:00Z")

</div>

Wouldn’t it be better to have the pattern matching over `Seq` built into OCaml? It will be almost a complete replacement to stream parsers.

Especially, since making `ocamllex` to return a `Seq.t` is quite easy.

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [February 8, 2022, 9:12am UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/14 "2022-02-08T09:12:22Z")

</div>

> [@vrotaru](#):
>
> Wouldn’t it be better to have the pattern matching over `Seq` built into OCaml? It will be almost a complete replacement to stream parsers.

Perhaps, but IMO this would come later. First this needs to be experimented with outside of the compiler; once that is done and a consensual design (and implementation!) is ready, we could consider the question of upstreaming…

Cheers,  
Nicolas

---

<div class="post-metadata">

**Author:** ![hyphenrf](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hyphenrf/32/2733_2.png) [@hyphenrf](https://discuss.ocaml.org/u/hyphenrf)\
**Post date:** [February 8, 2022, 1:32pm UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/15 "2022-02-08T13:32:09Z")

</div>

fwiw, [pyret](https://www.pyret.org/) has an [interesting approach](https://www.pyret.org/docs/latest/Expressions.html#%28part._s~3aconstruct-expr%29) to generic collection literals, which I plan to replicate once the experiment with `ppx_seq` proves frictionless. their approach allows you to construct all kinds of collections using a uniform syntax.

If the generic collections ppx turns out popular, maybe it’d be good to include it eventually as some lightweight sugar for OCaml… perhaps something like `Seq.[1;2;3], LazyList.[1;2;3], IntSet.[1;2;3], IntMap.[1, "one"; 2, "two"]` etc… where intermediate lists aren’t constructed, and delay semantics (or any kind of pre-construction operations really) are respected.

---

<div class="post-metadata">

**Author:** ![Chet\_Murthy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chet_murthy/32/1501_2.png) [@Chet\_Murthy](https://discuss.ocaml.org/u/Chet_Murthy)\
**Post date:** [February 8, 2022, 1:42pm UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/16 "2022-02-08T13:42:59Z")

</div>

Obviously questions of commodious syntax are ripe for _de gustibus non est disputandem_. But I think you’ll find it difficult to come up with a nice syntax for “seq parsers” while staying within the syntax of OCaml. While I agree that for many, many uses one doesn’t need to full power of Camlp5 (PPX attributes & extensions suffice), there are others where it’s simply necessary, and stream-parsers is one.

But it’s all good, I’m not trying to convince anybody.

---

<div class="post-metadata">

**Author:** ![hyphenrf](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hyphenrf/32/2733_2.png) [@hyphenrf](https://discuss.ocaml.org/u/hyphenrf)\
**Post date:** [February 12, 2022, 11:55am UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/17 "2022-02-12T11:55:46Z")

</div>

By the way, @silene, would you mind taking a look at the newest release docs? [Documentation · ppx\_seq 0.3.1 · OCaml Packages](https://v3.ocaml.org/p/ppx_seq/0.3.1/doc/index.html)  
I tried to clarify as much as possible the semantics of the macros. Any feedback is appreciated!

---

<div class="post-metadata">

**Author:** ![silene](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/silene/32/2707_2.png) [@silene](https://discuss.ocaml.org/u/silene)\
**Post date:** [February 16, 2022, 8:38am UTC](https://discuss.ocaml.org/t/ann-ppx-seq-v0-1-1/9227/18 "2022-02-16T08:38:11Z")

</div>

> [@hyphenrf](#):
>
> would you mind taking a look at the newest release docs?

No ambiguity, this looks good.
