ReasonML: Modules

March 13, 2018

Recently, I’ve been investing quite a lot in learning ReasonML and TBH I’m pretty much dead as JS developer right now because I’ve seen the better world. Much better one.

As a part of “Selling ReasonML to my colleagues” campaign (and to anyone, really), I’m going to spam your feeds from time to time with ReasonML related write-ups (hopefully, plural!). I’m too lazy these days to do epic monolithic posts so it’s going to be almost twitter-like shout-outs about the features I’m excited about the most.

Ok, first one is definitely about modules. It seems this is the number one thing that confuses the most of newcomers from JS world (I was there!) so let’s start with it.

Fact #1: Each .re file is a module

Let’s say you created new file Math.re. Boom, you have a new module in your app called Math.

By convention, all filenames are capitalized to match module name. You can name file math.re but module name is still capitalized: Math.

Fact #2: All content of a module is exported by default

If you create a type or a function or whatever inside your module it’s automatically available for module’s consumers using dot notation.

let sum = (a, b) => a + b;

/* Now you can use `Math.sum` in another module */
re
Math.re

Fact #3: All modules are available globally

Let’s say you created file App.re and want to use sum function from Math. How can you import it? The answer is “You don’t need to!”. All your root modules are available everywhere in your app. You can use any of them once you need it without messing with imports.

let onePlusTwo = Math.sum(1, 2);
re
App.re

Imagine when you implement some UI where you need Button, Input, Link etc etc: every time you need a new component in JS you have to go up, import it, go back to where you were. With Reason, you can just use whatever you want right here right now without interrupting your flow. So good! Once you’ll start using it, you’ll get how brilliant this is.

Fact #4: No folders (for the compiler), all filenames must be unique

Of course, you can use folders to group your files as you usually do (requires a bit of configuration) but for the compiler, all your files within a project is a flat list of modules. So all your files, no matter where they are located, must have unique names (remember, all modules are available globally). Compiler backs you up in case you accidentally created a file with a non-unique name.

At the very beginning, it might seem inconvenient constraint but in reality, it makes the naming of your modules accurate and explicit across the entire app.

E.g. in JS you can easily get into this state:

export default AuthButton extends React.Component {}
js
LoginButton.js
import Button from "./LoginButton";
js
LoginForm.js

What a mess! If you ever decide to rename your component you have to change all these places to keep your naming accurate. Meh. In Reason world, you have only one source of truth: file name. So it’s always guaranteed accurate across the entire app.


More about the ReasonML modules in the official documentation.

share