Writing OCaml using S-expressions

I wonder if OCaml code can be expressed using lisp-like syntax with s-expressions. Are there any features that would prevent the possibility? Are you aware if anyone has tried such an approach?

I come from a Lisp background. OCaml intrugues me and I would like to learn more about staticly-typed functional programming. However, I think that code as data feature of Lisp is very desirable and it would be cool to get the benefits of OCaml but write it using s-expression syntax.

2 Likes

I remember a camlp5 syntax extension which allows LISP-like syntax. IMHO nobody in same state of mind uses it.

Don’t expect code = data, it doesn’t go well in presence of types. AFAIR METAOCcaml have solved this problem somehow but I can’t say that it is popular way to write OCaml.

There is a toy project here which does exactly this https://github.com/jaredly/myntax

2 Likes

Thanks for the pointers, those look like interesting projects worth exploring more.

To follow on to what kakadu said, it’s worth considering that perhaps camlp5 is what you’re looking for. To wit, Ocaml has two properties:

(a) everything is strongly-typed

(b) there is a strict phase distinction between -code- (before compilation) and -execution- (after compilation)

This makes the … intermingling of execution and compilation that LISP uses, impossible. Instead, both camlp5 and the PPX extensions require that the programmer (well, the Makefile/dune-file writer) enforce that phase distinction, telling the Makefile the “T-diagram” (https://en.wikipedia.org/wiki/Tombstone_diagram) involved in expanding all the macros, etc, etc.

In that context, camlp5 provides the full abstract syntax of ML, along with tools to do pattern-matching, pattern-instantiation, and the ability to define macros.

Just as it’s possible in LISP to define macros to the point where the language you’re programming in is … alien, you can do the same with camlp5.

2 Likes

I am aware that run-time eval is a thing that will have to be sacrificed. However, my experience with Clojure taught me that run-time eval is not needed for most programs. As such compile-time only macros can be plenty of powerful.

After a quick look at both Myntax and camlp5 I think I will start tinkering with Myntax first. It has a grammar based on Clojure inspired syntax which I consider more user friendly than that of traditional lisps. For code generation uses ReasonML AST helpers, so it should be possible to cover all constructs too.

Camlp5 seems more powerful, but also more complicated :slight_smile:

It’s Ocaml AST by the way :slight_smile:

I’m sorry, I was garbled. What I meant was that in LISP, there is no clear “compile, then eval” rule; instead, evaluation (of macros and the code they call) is intermixed with compilation. Whereas, in all ML-derived languages (that I know of) this is simply impossible (due to strict type- and naming- discipline). So camlp5 does the next best thing: gives you complete ability to redefine the entire syntax, along with interposing your own code between the new syntax and the eventual AST which the ocaml compiler will compile into executable code.

Now of course, the -syntax- that campl5 accepts is ML-like. But that’s only necessary: if you’re going to reach ML programmers, you’re not going to do it with a syntax that isn’t very close to what they program with every day. And the camlp5 is itself strictly typed; again, b/c ML programmers expect things to be strictly-typed, and the eventual AST is strictly typed, too.

It sound like what you want, is a LISP-like AST for ocaml, on which you’ll define your own macro-expander language? Uh, I guess that might work, but … well, I suspect it’s going to be a really heavy lift.

You can get a sexp syntax using camlp5: https://camlp5.github.io/doc/htmlc/scheme.html

I don’t think I have ever seen that used in the wild, but it may be fun to play with.