I’ve been writing plenty about Rescript this year, although I’ve taken a bit of a hiatus to focus on developing a couple (Rescript) open source libraries. I wanted to get back into blogging to answer one of the most confusing questions in the Rescript community: What is ReasonML and how does it relate to Rescript?
However, it has grown into something quite a bit bigger. Instead, we’ll be talking about the relationships between a collection of several interrelated languages, and I’ll give my opinion on which you should use.
I specifically want to discuss the current state of these languages, rather than digging into their history. I make recommendations that are based entirely on my opinion. To help guide your own decisions, I indicate my experience level with each language, as familiarity has a habit of generating both delight and disatisfaction.
Table of Contents
This series takes a lot of time to write and maintain, and I don’t always have enough motivation to keep it up. I’m not one for begging for money on the Internet, but if you’re interested in providing some of that motivation, I’ve set up a Patreon account. I thank you for your support.
Other articles in this series
With over a dozen articles and counting, I’ve created a table of contents listing all the articles in this series in reading order.
This article is a stand-alone informational piece not connected to any of the existing tutorials.
OCAML is the oldest of the languages under consideration, and I doubt any programming language invented in the last 15 years hasn’t taken inspiration from OCAML in one form or another. That said, relatively few people (including myself) actually know the language well.
I’d say the two defining features of OCAML are a functional paradigm and static typing with best-in-class type inferencing. I find it a rather strange looking language, but that’s more a reflection of my own language history than the language itself.
I’ve read through OCAML tutorials and set up the compiler with hello world and the like, but I haven’t actually written even a toy app in it. Learning the language better is on my todo list.
On Static Typing
I want to delve a little deeper into the static typing thing. Static typing is overhyped by its proponents and over-disparaged by its detractors.
Static typing is great for documentation. I like not having to scatter
style declarations in documentation strings just to indicate that a dynamically
typed function is supposed to expect an integer. That’s just silly.
Extending that, static typing is great for finding documentation about types. Modern editors using language servers can easily find and display the types for functions you are about to call.
Some argue that static typing provides performance benefits, but I’m not convinced. Static types are easier to compile to native architectures, and are therefore typically more performant, but that doesn’t strictly mean that static typing is a necessary condition for performance.
A key benefit of static typing is that it acts as a sort of sanity check that 100% of your code is valid syntax. In dynamic programming languages, you need 100% test coverage to be confident that every line of code is syntactically correct. Static checks help get you that baseline test coverage for free.
One drawback of static typing is that it’s necessarily verbose. It sucks when a language forces you to “write the same thing over here that you wrote over there” for no reason other than to prove you spelled the word “integer” correctly. This is why OCAML (and it’s derivatives) outstanding type inferencing is so important. If the compiler can infer the type, you don’t have to write it in, and your code is better for it.
Static typing can also cost a lot of developer time when you’re trying to figure out what type a specific value or function should have. If you spend fifteen minutes trying to figure out how to satisfy a compiler even though you know your code is correct, static typing has failed you.
OCAML: Recommended Uses
In my opinion, everyone should learn OCAML and then avoid using it in production. Knowing OCAML will, I think, help make better decisions and think differently when coding in other languages.
However, I woludn’t use it in a production system, if for no other reason that hiring people for the role would be virtually impossible! Further, if I was going to build a production native app, I would do it in Reason (see below) instead, as it appears a bit more approachable.
I have a couple other beefs with the language. First, it’s bloody slow to compile. Building anything with Typescript just pulls me straight out of the flow. Modern tooling such as esbuild has improved this, but it’s nothing compared to what I’ve become used to with Rescript.
Second, Typescript is huge. Learning all the language features takes quite a bit of trouble. I particularly hate having to track down some esoteric syntax to satisfy the compiler when I know the code is behaving correctly (I dislike Rust for the same reason).
code fit the typed paradigm. Things like
Partial are really useful
and common in Typescript code that has to interface with older JS code. They
satisfy the compiler, but such constructs do not make the code easier to reason
about. Further, I still have to search the web every time I want to sort out
typing on generic costructs.
I am reasonably familiar with Typescript. I’ve written entire real world applications in it and occasionally dive into Typecript code for my day job.
Typescript: Recommended Uses
I personally believe that Rescript (discussed in a bit) is a better choice for developing, however. I actually think that Rescript will overtake Typescript in popularity at some point. But I could be wrong about that. I generally believe that popular languages and frameworks get better faster than good ones get popular. There is a lot to be said for doubling down on Typescript; it’s easy to hire for and easy to train in (though not to master).
A note on Flow
Flow is a direct competitor to Typescript and does exactly the same thing. It’s main advantage over Typescript is that it is soundly typed. However, this is outweighed by the disadvantage that Facebook is intentionally not developing flow for public consumption anymore. Typescript has won that race and open source Flow will never catch up. If you don’t work for and have no intention of applying to Facebook (though I can say from experience that it’s an amazing place to work), you probably shouldn’t bother with Flow.
ReasonML is best described as an alternate syntax to OCAML. It uses the exact same syntax as OCAML, and you can access the same OCAML libraries. Indeed, it even uses the same compiler toolchain.
The drawback is that it has an even smaller community. Plenty of real companies use and support Reason (and the underlynig OCAML toolchain), but it is still rather niche.
Another drawback is that the Reason documentation and ecosystem is structured such that you need to have a decent understanding of the OCAML ecosystem in order to use and understand Reason. One of the reasons I suggested people learn OCAML above is that knowing it will make certain aspects of Reason development simpler.
I have a little more familiarity with Reason that I do with OCAML, which isn’t much. I intend to do some future articles on Reason to explore native apps, but I’m not sure when that will happen!
Reason: Recommended Uses
This is a pretty weak opinion, but I think Reason should be considered for backend service and native development, especially if the rest of your ecosystem is in Rescript.
I hinted (ok, it was pretty blatant, not really a hint at all) earlier that I’m not a fan of Electron. It is ridiculous to ship a separate copy of Chrome with every desktop app these days. I would be inclined to build something on Reason and Revery instead, if I was planning to build native UI. That said, I would look very hard at this decision for production code because it would not be easy to hire developers to maintain it!
Ok, I’ve written a lot about Rescript and it’s no secret that I love it, so we can skip some of the intro. Rescript looks like it’s part of the OCAML ecosystem, but that’s not strictly true and is becoming less true every day. Rescript started out as a variation of Reason, but is now so much more. Valid Rescript syntax looks similar to Reason, but Reason is no longer backwards compatible with Rescript, and this gap is widening as Rescript continues to improve.
In contrast to Typescript, Rescript is a very small, tight, tidy language. It is soundly typed with amazing type infreencing. It is incredibly fast to compile.
The one drawback of Rescript compared to Typescript is that it has a much smaller community. You have to write your own bindings most of the time. If you need support, your one and only recourse is the (very active, but small) Rescript forum.
Rescript: Recommended Uses
Barring that caveat, I personally recommend Rescript for all web frontend development.
As I mentioned in the Reason recommendations, if you are using Rescript for your frontend, you may want to experiment with Reason for your backend. I don’t have enough experience one way or the other to explicitly recommend this right now. But stay tuned, I will be doing some experimenting with it soon!