# Let+ syntax backported to OCaml \>= 4.02

**URL:** https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447
**Category:** Community
**Tags:** ocaml, dune
**Created:** [March 6, 2019, 3:37pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447 "2019-03-06T15:37:20Z")
**Posts on this page:** 18
**Page:** 1

<div class="post-metadata">

### Author: ![jeremiedimino](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jeremiedimino/32/699_2.png) [@jeremiedimino](https://discuss.ocaml.org/u/jeremiedimino)
#### Post date: [March 6, 2019, 3:37pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/1 "2019-03-06T15:37:20Z")

</div>

Hi,

The upcoming OCaml 4.08 release will allow developers to define custom bindings operators. We were eager to use this feature in the code of Dune but because we are currently keeping compatibility with all versions of OCaml since 4.02, we decided to implement a preprocessor shim for older OCaml versions. Given that this shim works quite well, we are also making it available for users of Dune starting with version 1.8 which will be released soon. This post explains how to use this new feature.

## The future\_syntax preprocessor

If you want to use custom bindings in your code but need to keep your code compatible with OCaml \< 4.08, you can use the special `future_syntax` preprocessor introduced in Dune 1.8. To do that, simply add the following field to your library/executable stanza:

```auto
(preprocess future_syntax)

```

When using OCaml \>= 4.08, this is exactly equivalent to just deleting this field. This means that `future_syntax` doesn’t add overheard when using a recent version of the compiler. When using using OCaml \< 4.08, this will automatically add a pre-processor that will translate special `let+`, `let*`, `and+`, … operators into valid pre-4.08 OCaml code, allowing your code to compile with an older compiler.

## Limitation

The shim preprocessor converts bindings operators to OCaml identifiers of the form `let __XXX` and `and__ XXX`. For instance, `let+*` is translated to `let__plus_star`. So you must make sure to not use such identifiers in your code.

## Complete example

The following example uses the `future_syntax` preprocessor and bindings operators in code using the cmdliner library.

`dune` file:

```auto
(executable
 (name foo)
 (libraries cmdliner)
 (preprocess future_syntax))

```

`foo.ml` file:

```ocaml
open Cmdliner

let ( let+ ) t f =
  Term.(const f $ t)
let ( and+ ) a b =
  Term.(const (fun x y -> x, y) $ a $ b)

let term =
  let+ a = Arg.(value & flag & info ["a"] ~doc:"blah")
  and+ b = Arg.(value & flag & info ["b"] ~doc:"blah")
  and+ c = Arg.(value & flag & info ["c"] ~doc:"blah")
  in
  Printf.printf "a=%B b=%B c=%B\n" a b c

let cmd = (term, Term.info "foo" ~version:"v1.0.3" ~doc:"example")

let () = Term.(exit @@ eval cmd)

```

You can test this example with:

```bash
$ dune exec ./foo.exe -- -a -b

```

Without bindingins operators, `foo.ml` would have to be written as follow:

```ocaml
open Cmdliner

let term =
  let main a b c =
    Printf.printf "a=%B b=%B c=%B\n" a b c
  in
  Term.(const main
        $ Arg.(value & flag & info ["a"] ~doc:"blah")
        $ Arg.(value & flag & info ["b"] ~doc:"blah")
        $ Arg.(value & flag & info ["c"] ~doc:"blah")
       )

let cmd = (term, Term.info "foo" ~version:"v1.0.3" ~doc:"example")

let () = Term.(exit @@ eval cmd)

```

Which shows that binding operators are especially nice when working with such API; indeed, without binding operators the authors and readers of the code have to manually match the order of arguments passed to `main` with the order of the `Arg.(...)` expressions inside the `Term.(...)` expression. With binding operators, the OCaml variable to which the evaluation of the command line argument is bound is right next to its definition, which is much nicer to read and write.

---

<div class="post-metadata">

### Author: ![rdavison](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/rdavison/32/4321_2.png) [@rdavison](https://discuss.ocaml.org/u/rdavison)
#### Post date: [March 6, 2019, 7:30pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/2 "2019-03-06T19:30:38Z")

</div>

This looks awesome! Just got a question about versioning of the `future_syntax` preprocessor. I like how easy it is to specify it in the dune files, but I’m concerned about what will happen if one day you want to deprecate this preprocessor and support yet another “future\_syntax”.

For example, in the python2 community, it’s common to see people specifically select which future syntaxes to use by writing:

```python
from __future__ import print_function

```

---

<div class="post-metadata">

### Author: ![jeremiedimino](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jeremiedimino/32/699_2.png) [@jeremiedimino](https://discuss.ocaml.org/u/jeremiedimino)
#### Post date: [March 7, 2019, 7:37am UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/3 "2019-03-07T07:37:35Z")

</div>

`future_syntax` will be versioned in the same way as other features provided by dune. If in the future we decide to change what `future_syntax` means, then its meaning will simply be tied to the `(lang dune x.y)` you write in your `dune-project` file.

That said, I don’t think we will be able to provide much more than custom binding operators in dune. Indeed, the only form of extensibility provided by the OCaml parser is a lexer hook and ast mappers. This was enough to easily retrofit the let+ syntax, but it won’t be enough for other more complex new syntax forms. At some point, we would need to import the whole OCaml frontend, which doesn’t seem viable.

---

<div class="post-metadata">

### Author: ![hcarty](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hcarty/32/1824_2.png) [@hcarty](https://discuss.ocaml.org/u/hcarty)
#### Post date: [March 7, 2019, 4:48pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/4 "2019-03-07T16:48:22Z")

</div>

Is `future_syntax` specific to code using OCaml syntax or would it work with Reason syntax as well?

---

<div class="post-metadata">

### Author: ![jeremiedimino](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jeremiedimino/32/699_2.png) [@jeremiedimino](https://discuss.ocaml.org/u/jeremiedimino)
#### Post date: [March 7, 2019, 5:21pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/5 "2019-03-07T17:21:29Z")

</div>

It is specific to code using OCaml syntax. For Reason, `refmt` would be the right place to provide such a feature.

---

<div class="post-metadata">

### Author: ![hcarty](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/hcarty/32/1824_2.png) [@hcarty](https://discuss.ocaml.org/u/hcarty)
#### Post date: [March 7, 2019, 5:33pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/6 "2019-03-07T17:33:11Z")

</div>

Thanks @jeremiedimino, I thought that was the case but wanted to be sure.

---

<div class="post-metadata">

### Author: ![lpw25](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lpw25/32/144_2.png) [@lpw25](https://discuss.ocaml.org/u/lpw25)
#### Post date: [March 7, 2019, 9:24pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/7 "2019-03-07T21:24:47Z")

</div>

If it’s only going to provide let syntax then perhaps a more specific name like: `let_syntax_shim` or `binding_operators_shim` would be better.

---

<div class="post-metadata">

### Author: ![jeremiedimino](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jeremiedimino/32/699_2.png) [@jeremiedimino](https://discuss.ocaml.org/u/jeremiedimino)
#### Post date: [March 11, 2019, 11:44am UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/8 "2019-03-11T11:44:39Z")

</div>

We’ll also support things like `match+` if they are added to the language

---

<div class="post-metadata">

### Author: ![Freyr666](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/freyr666/32/591_2.png) [@Freyr666](https://discuss.ocaml.org/u/Freyr666)
#### Post date: [March 11, 2019, 12:24pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/9 "2019-03-11T12:24:19Z")

</div>

For some reason it doesn’t work with functors for me:

```
module type Monad = sig
  type 'a t
  val bind : 'a t -> ('a -> 'b t) -> 'b t
end

module M (X : Monad) = struct
  let ( let* ) = X.bind
end

let comp () =
  let open M (Option) in (* Syntax error *)
  let* x = Some 42 in
  None

File "lib/let/let.ml", line 53, characters 13-14:
Error: Syntax error
```

---

<div class="post-metadata">

### Author: ![jeremiedimino](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jeremiedimino/32/699_2.png) [@jeremiedimino](https://discuss.ocaml.org/u/jeremiedimino)
#### Post date: [March 11, 2019, 12:46pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/10 "2019-03-11T12:46:26Z")

</div>

Note that `let open M (Option) in ...` is a new syntax in 4.08. It is not covered by `(preprocess future_syntax)`.

---

<div class="post-metadata">

### Author: ![Freyr666](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/freyr666/32/591_2.png) [@Freyr666](https://discuss.ocaml.org/u/Freyr666)
#### Post date: [March 11, 2019, 1:02pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/11 "2019-03-11T13:02:43Z")

</div>

Ah, indeed. It doesn’t work with dune either, right?

---

<div class="post-metadata">

### Author: ![jeremiedimino](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jeremiedimino/32/699_2.png) [@jeremiedimino](https://discuss.ocaml.org/u/jeremiedimino)
#### Post date: [March 11, 2019, 1:27pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/12 "2019-03-11T13:27:34Z")

</div>

Do you mean when you use `(preprocess future_syntax)`? No, it doesn’t. We couldn’t provide a shim for this syntax without copy&pasting a lot of code from the compiler. `let+` was a special case.

---

<div class="post-metadata">

### Author: ![BikalGurung](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bikalgurung/32/5105_2.png) [@BikalGurung](https://discuss.ocaml.org/u/BikalGurung)
#### Post date: [May 6, 2019, 3:55pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/13 "2019-05-06T15:55:17Z")

</div>

How do we use `future_syntax` with other ppx? For example, I am trying to use `future_syntax` with `ppx_let` but getting an error from dune.

```auto
$ cat dune
(executable
 (name test_let_syntax)
 (preprocess
  (future_syntax)
  (pps lwt_ppx ppx_let))
 (libraries lwt_ppx uri lwt lwt.unix str))

$ cat test.ml
let (let*) = Lwt.bind

let () = 
  let* line = Lwt_io.(read_line stdin) in 
  Lwt_io.printlf("%s", line)

```

The above is giving me the compilation error as below,

```auto
File "src/dune", line 7, characters 2-23:
7 | (pps lwt_ppx ppx_let))
      ^^^^^^^^^^^^^^^^^^^^^
Error: Too many argument for preprocess

```

What gives?

```auto

```

---

<div class="post-metadata">

### Author: ![rdavison](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/rdavison/32/4321_2.png) [@rdavison](https://discuss.ocaml.org/u/rdavison)
#### Post date: [May 6, 2019, 4:10pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/14 "2019-05-06T16:10:28Z")

</div>

~~I had the same question. It doesn’t work with other preprocessors. Here’s the response. tl;dr: It would need to be implemented in `ppxlib` in order to become compatible with other preprocessors, but doing so requires non-trivial amount of work.~~

[What is holding you back from upgrading to the latest OCaml compiler?](https://discuss.ocaml.org/t/what-is-holding-you-back-from-upgrading-to-the-latest-ocaml-compiler/3753/5)

EDIT: Apparently there’s now better support in Dune 1.10. I haven’t tested yet though. Please see diml’s post below.

---

<div class="post-metadata">

### Author: ![jeremiedimino](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jeremiedimino/32/699_2.png) [@jeremiedimino](https://discuss.ocaml.org/u/jeremiedimino)
#### Post date: [May 6, 2019, 4:43pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/15 "2019-05-06T16:43:29Z")

</div>

Actually, following a few recent changes with dune 1.10 you should be able to do: `(pps lwt_ppx ppx_let -- -pp %{bin:ocaml-syntax-shims})`.

---

<div class="post-metadata">

### Author: ![Dean177](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dean177/32/1221_2.png) [@Dean177](https://discuss.ocaml.org/u/Dean177)
#### Post date: [June 6, 2019, 9:49pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/16 "2019-06-06T21:49:55Z")

</div>

Trying that gets me the following:  
`Error: %{bin:..} isn't allowed in this position`

This is on dune 1.10.0

Should I raise an issue in GitHub?

---

<div class="post-metadata">

### Author: ![jeremiedimino](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jeremiedimino/32/699_2.png) [@jeremiedimino](https://discuss.ocaml.org/u/jeremiedimino)
#### Post date: [June 7, 2019, 9:56pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/17 "2019-06-07T21:56:06Z")

</div>

Ah, we must have missed something here. Yes, please raise an issue on GitHub 🙂

---

<div class="post-metadata">

### Author: ![Dean177](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dean177/32/1221_2.png) [@Dean177](https://discuss.ocaml.org/u/Dean177)
#### Post date: [June 10, 2019, 9:54pm UTC](https://discuss.ocaml.org/t/let-syntax-backported-to-ocaml-4-02/3447/18 "2019-06-10T21:54:17Z")

</div>

Check here for a solution: [https://github.com/ocaml/dune/issues/2262](https://github.com/ocaml/dune/issues/2262)
