Enjoy Painless Typing With ReasonML!
Tags: reason, docker, javascript, react
Published: 2018-04-09 15:17:03

---
title: Enjoy Painless Typing With ReasonML!
published: true
description: ReasonML is one of the hypest language of the moment, and in my opinion, it's for good reasons. Let's discover this language together.
tags: reasonml,docker,js,react
canonical_url: https://marmelab.com/blog/2018/04/09/enjoy-painless-typing-with-reason.html
cover_image: https://marmelab.com/images/blog/reasonml/bigbanner.jpg
---

Note: This post was originally posted on [marmelab.com](https://marmelab.com/blog/2018/04/09/enjoy-painless-typing-with-reason.html).

For one of our regular hackdays at Marmelab, I wanted to learn a language I've kept in the back of my head since I heard of it at [React Europe 2017](https://marmelab.com/blog/2017/05/24/minutes-of-react-europe-2017.html).

This language, which is called [Reason](https://reasonml.github.io/) (shortcut for ReasonML), is in fact a syntax and a toolchain overlay for [OCaml](https://ocaml.org/index.fr.html), a language that is known for its robustness, its strong static typing, and its ubiquitous functional paradigm approach.

According to the Reason website, its main goal is to provide a friendly syntax / environment to JavaScript developers looking for performance, consistency, and type safety.

> Reason can almost be considered as a solidly statically typed, faster and simpler cousin of JavaScript, minus the historical crufts, plus the features of ES2030 you can use today, and with access to both the JS and the OCaml ecosystem!

By the way, I think that this simple example should suffice to illustrate its power, and whet your appetite for further reading.

```reason
type schoolPerson = Teacher | Director | Student(string);

let greeting = (stranger) =>
  switch (stranger) {
  | Teacher => "Hey professor!"
  | Director => "Hello director."
  | Student("Richard") => "Still here Ricky?"
  | Student(anyOtherName) => "Hey, " ++ anyOtherName ++ "."
  };
```

To explore this language in practice, I've coded a [reversi game](https://marmelab.com/reversi-reason/) running in the browser. I'll use it to give an overview of Reason capabilities, and explain why I think that it opens a whole new horizon on the JavaScript ecosystem.

But before going into technical details, let me introduce Reason from an historical and practical point of view.

## Reason Is OCaml Made Easier

As I previously said, Reason is based on OCaml. This way, it benefits from all the OCaml strengths, like polymorphic / infered typing, pattern matching, garbage collector, sophisticated module system, and so on.

OCaml is the main implementation of Caml. Caml is a safe, reliable, and expressive programming language created in 1985 by a French research institute in Computer Science called [INRIA](https://www.inria.fr/). But, what's wrong with OCaml? Why not use it directly? Indeed, the question deserves to be asked. 

OCaml is based on complex principles, and uses an awkward syntax. Here is an example of OCaml code, which adds values recursively from a list:

```ocaml
let rec sum xs =
  match xs with
    | [] -> 0
    | x :: xs' -> x + sum xs';;

(* sum [1;2;3;4;5] => 15 *)
```

**Tip**: As a matter of fact, it's not really necessary to use recursive functions for this kind of purpose, because the [Core Standard Library](https://caml.inria.fr/pub/docs/manual-ocaml/libref/index.html) has many built-in functions covering most needs.

The complexity of OCaml explains why OCaml it confined to academic projects for a long time.

Until a few years ago, [Jordan Walke](https://twitter.com/jordwalke), who works at Facebook, created the famous [React](https://reactjs.org/) library [using SML](https://www.reactiflux.com/transcripts/jordan-walke/) (a derived OCaml language), and created ReasonML. Shortly after, he made the decision to migrate ReactJS to plain JavaScript for a wider adoption.

<img src="https://marmelab.com/images/blog/reasonml/react.png" />

## BuckleScript Brings OCaml to the Web

In fact, Reason does not directly compile to JavaScript. For that purpose, it maintains a strong dependency to another library called [BuckleScript](https://bucklescript.github.io/).

BuckleScript defines itself as a "sister" project of Reason. In fact, **both share the same community** (they have the same [Discord](https://discord.gg/reasonml)), and the same purpose: bringing OCaml's capabilities to the browser. Moreover, the documentation between the two projects is very complementary.

Here is a little schema of the compilation workflow from Reason to JavaScript. Under the hood, reason files (`.re`) are transformed to plain OCaml [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) through an [OCaml preprocessor for Reason](https://github.com/reasonml/reason-cli). This OCaml AST is then processed by the [BuckleScript compiler](https://github.com/BuckleScript/bucklescript) called `bsc`, which produces plain JS Files.

<img src="https://marmelab.com/images/blog/reasonml/reasontojs.png" />

The compilation process is a bit more complex than explained here. To understand it in more details, I suggest you take a look at [this excellent repository](https://github.com/chenglou/intro-to-reason-compilation) owned by [chenglou](https://github.com/chenglou), the speaker who introduced me to Reason at [React Europe](https://www.react-europe.org/).

## Why Not TypeScript Or Flow?

JavaScript is an untyped language, but large projects often require additional programming safety throught types. That's why many tools have been created on top of JavaScript to fill this gap. Among them, the most popular are probably [TypeScript](https://www.typescriptlang.org/) and [Flow](https://flow.org/).

<img src="https://marmelab.com/images/blog/reasonml/tsvsflow.png" />

* **TypeScript** is an open-source programming language developed by Microsoft. It acts as a strict **syntaxic superset of JavaScript** that adds static typing to it. It is also considered as first class language for [Angular](https://angular.io/) development.
* **Flow** is an open-source static type checker for JavaScript developed by Facebook. It acts as a **specific syntax (kind of annotations) which adds types** over an existing code.

How does Reason compare to those two? In fact, Reason is not a new syntax for JavaScript, or a simple typing overlay. **Reason is a complete language**. It introduces new control structures that you'll never find in TypeScript or Flow. Reason is built with typing at its core, and just *compiles* to JavaScript. 

If you need strong types, I think that the only valid reason to use TypeScript or Flow is to port an existing JavaScript codebase. If you need strong types without an existing codebase, prefer a real typed language like Reason.

## Reason Can Compile To Other Platforms

Reason uses OCaml as an intermediate language, and it's BuckleScript's job to translate that OCaml code into JavaScript. 

But there are other toolchains for running OCaml code in other platforms. For instance, OCaml can be compiled to native code, thanks to the [ocamlopt compiler](http://caml.inria.fr/pub/docs/manual-ocaml-4.00/manual025.html). In this respect, there are some successful [cross-platform projects](https://jaredforsyth.com/posts/making-a-cross-platform-mobile-game-in-reason-ocaml/) written in Reason that are compiled to native, browser, Android and iOS.

From my point of view, this unexpected possibility opens up a whole new development horizon. Above all, this opportunity allows to move away from the "all JavaScript" trend, which I think is dangerous. We should never lock ourselves with a single technology.

OK, enough with the introduction of the language. Let's see some code!

## Bindings And Expressions

Unlike JavaScript, there's only **one way to declare / assign variables** in Reason. Indeed, because everything is immutable by nature, the only assignation keyword is `let`. Therefore, the assignment action is called a "let binding".

```reason
let message = "hello world";
```

"Immutability" means that a value can't change over time - it doesn't means that you can't create a new binding with the same name to replace an existing one. That's why `let` is called a *binding* and not an *assignment*. **A binding gives a name to a value**, it doesn't change the value.

```reason
let message = "hello";
print_endline(message); /* Prints "hello" */
/* totally legal */
let message = "world";
print_endline(message); /* Prints "world" */
```

To effectively change an already bound "value", you must use a `ref`. This topic is discussed later in the "An Imperative Way Out" section.

Bindings can also be scoped into a "block" scope (`{}`). In that case, the last expression of the block is implicitly returned. There's no explicit `return` in Reason. As in JavaScript, **bindings are only available in theirs respective scopes.**

```reason
let message = {
    let part1 = "hello";
    let part2 = "world";
    part1 ++ " " ++ part2
};

/* part1 & part2 not availables here */
```

## Basic Types

Like most other programming languages, Reason supports all basic types such as booleans, numbers, strings and chars. Since Reason is a statically typed language, **types can be manually defined, or can be infered at compile time** from the program AST.

```reason
let score = 10; /* type is infered */
let score: int = 10; /* type is manually defined */
```

With Reason, just like with Python, there's no implicit type casting. **Developers must use explicit type conversion functions** (like `string_of_int` or `string_of_bool`) to switch from one type to another. These functions are part of [Pervasives](https://reasonml.github.io/api/Pervasives.html), which is the initially opened module at the beginning of each compilation. It provides all the basic operations over the built-in types. 

## Custom Types

As in OCaml, it is also possible to create your own types with Reason. In this respect, here are 2 different kinds of types from the reversi "Cell" module. 

The `color` type is called a [Variant](https://reasonml.github.io/docs/en/variant.html). A Variant is a kind of **group of possible constants**. These constants, which are called "constructors" or "tags", are separated by "|" bars. Variants are, from my point of view, the key feature of Reason. They allow us to carry values (as arguments), and enable pattern matching.

```reason
/* cell.re */
type color = White | Black;
```

The `cell` type is called a [Record](https://reasonml.github.io/docs/en/record.html). In other languages, it's usually called a `struct`. Objects created based on a Record are immutable, fixed, and very fast. Records needs a strong type definition. That's why each field is explicitly typed.

```reason
/* cell.re */
type cell = {
    x: int,
    y: int,
    color: option(color),
};
```

As you see for the `color` field of the `cell` type, a type can contains another type. It allows to create [complex recursives data structures](http://2ality.com/2017/12/variants-reasonml.html#self-recursive-data-structures-via-variants) (like trees) quickly and easily.

```reason
type intTree =
  | Empty
  | Node(int, intTree, intTree);
```

## Parameterized And Special Types

In one of the previous example, you may have asked yourself about the `option(color)` function call. In fact, `option` is not a function, it's a parameterized Variant, which is directly exposed by the [standard library](https://reasonml.github.io/api/index.html).

Since there's no `null` values in Reason (and therefore no null pointer exceptions), `option` allows to mimic the absence of value for anything. It can either be `None` (`null` equivalent) or `Some(value)`. It can be compared to the famous [Maybe](https://en.wikibooks.org/wiki/Haskell/Understanding_monads/Maybe) Monad.

```reason
type option('a) =
    | None
    | Some('a);
```

What does the `'a` mean? In Reason, **every type can accept parameters**. The unique quote means "a value of any type". This is very useful to create generic type structures.

## Lists And Arrays

In Reason, one of the most used Type is [List](https://reasonml.github.io/docs/en/list-and-array.html#list). As its name suggests, a List is a collection of elements that are of the same type.

Lists are represented as [linked lists](https://en.wikipedia.org/wiki/Linked_list) underneath (even [in the transpiled JavaScript!](https://reasonml.github.io/en/try.html?reason=DYUwLgBAJglgTiAxmGB7AdgZwgXggbQCgISIAKABgBoIBGAShogHoAqCAZRNeeNMpoBaBjTYQAct16lytGhUYkxAUSl8SZOXUUt2HVT3W6IAOjMRDAXQDcQA)). Because of that, they're **dynamically sized and immutable** by nature, and they allow to add or remove elements very quickly.

```reason
/* board.re */
let directions = [
    (0, 1),  /* S  */
    (0, -1), /* N  */
    (1, 0),  /* E  */
    (1, 1),  /* SE */
    /* ... */
];
```

Lists are very fast for updates, but very slow for access. Read operation speed is proportional to the size of the List (**O(n) complexity**). That's why Reason also provide an [Array](https://reasonml.github.io/docs/en/list-and-array.html#array) Type.

Contrary to Lists, **Arrays are fixed-size collections**, which are mutable and fast for read operations (**O(1) complexity**).

```reason
let myArray = [|"hello", "world", "how are you"|];
```

In brief, Lists are better for dynamic and medium sized collections that do not require fast access. Array are better for fixed and large sized collections that require fast access.

You'll find more information about Lists and Arrays in the [Exploring ReasonML online book](http://reasonmlhub.com/exploring-reasonml/ch_arrays.html#lists-vs.arrays), which is very complete.

## Pattern Matching And Destructuring

I've introduced Types and Variants so that I can talk about one of the most interesting feature of Reason: pattern matching.

<img src="https://marmelab.com/images/blog/reasonml/matching.png" />

In brief, pattern matching allows both to check and to extract data from structures. It's a kind of mix between [RegExp.test](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/RegExp/test) and [RegExp.exec](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/RegExp/exec) from JavaScript, but for all types of data, and anywhere (bindings and function args).

In the following example, I use the `switch` expression to test the `color` value against multiple patterns. When a pattern matches, the value just after the `=>` is then returned and assigned to "identifier".

```reason
/* cell.re */
let identifier = switch (color) {
    | Some(Black) => "black"
    | Some(White) => "white"
    | None => ""
};
```

The above example is of course the simplest one. You can also match one part of the value, use it afterwards, and even match on an exception!

```reason
/* board.re */
let getCell = (x, y, cells) =>
    switch (List.find(cell => cell.x == x && cell.y == y, cells)) {
        | ({ color }) => color /* color is extracted from the cell record */
        | exception Not_found => None
    };
```

Naturally, matching also comes with [destructuring](https://reasonml.github.io/docs/en/destructuring.html). That's why it's even possible to extract parts of data structures easily, even from functions args!

```reason
/* board.re */
let init = (width, height) => {
    let (mw, mh) = (width / 2, height / 2); /* tuple destructuring */
    /* ... */
};

let isOutOfBound = ({ width, height }, (x, y)) => /* function args destructuring */
    x < 0 || y < 0 || x > (width - 1) || y > (height - 1);
```

There are a lot of things to say about pattern matching, far too much to cover everything here. I advise you to take a look at [this article](http://2ality.com/2017/12/pattern-matching-reasonml.html), which is very comprehensive.

## Functions

As you may have understood, Reason is fully focused on the functional paradigm. In this regard, it highlights a lot of concepts like **higher-order functions**, **recursivity**, **partial application** (via currying), and so on. The Reason function syntax is very close to the [ES6](http://exploringjs.com/es6/index.html) one. It uses the famous "arrow / body" pair.

```reason
let add = (first, second) => first + second;
add(1,2); /* 3 */
```

In Reason, every function takes at least one argument, even if you don't declare / notice it! When you declare a function without any argument, under the hood, Reason adds a [unit](https://reasonml.github.io/docs/en/function.html#no-argument) argument to it. In the example below, the pair of brackets `()` after `locationReload` is a `unit`. So, in reality, you effectively call `locationReload` with an argument without even realizing it.

```reason
let locationReload = () => {
  /* ... */
};
locationReload();
```

You may be disappointed by this "unit", but you must known that it's a normal value. Above all, you must not confuse "unit" with an "option". Whereas an "option" represents "a value or an empty value", a "unit" represents an absence of value (think about `undefined` or "nothing").

## Currying

Reason offers built-in [currying](https://reasonml.github.io/docs/en/function.html#currying) of all functions. That means that every function with one or more arguments is transformed into a series of functions with one argument. 

```reason
let add = (first, second) => first + second;
add(1)(2); /* 3 */
```

You may think that it's a waste of resources to create additional function calls, but it's not. OCaml optimizes the output to avoid unnecessary function allocation if partial functions are never called in your program ([see this example](https://reasonml.github.io/en/try.html?reason=DYUwLgBAhgJjEF4IAoAeBKRA+FBPTCOqEA1BLgNwBQVA9AFQTAD2zA1tJGABYgTMBXMAAchAQmhwAYgEsAbnxkBnaBAD6SmQDsA5qDUQAZgK0BjMDOZaIpqMGAT6tKqEiwYshYkkxkAVnRqF3AITWIkd08QZABGQKA)). This way, OCaml provides out of the box currying without any performance penalty.

Here is another example of currying, where I take advantage of partial application for my `getCountForColor` function from the reversi `Board` module:

```reason
let getCountForColor = (board, color) =>
    board.cells
        |> List.filter(c => c.color == color)
        |> List.length;

let countForColorFromMyBoard = getCountForColor(myBoard);

let countWhite = countForColorFromMyBoard(Some(White));
let countBlack = countForColorFromMyBoard(Some(Black));
```

The pipe operator `|>` (also called "reverse-application operator") allows to pass the result of an expression as the first argument of the following expression. Think of the Linux pipe. Given that functions natively allow partial application, it works like a charm!

## Labeled Arguments

Reason functions also work with named arguments (called [labeled arguments](https://reasonml.github.io/docs/en/function.html#labeled-arguments)). They are compatible with currying as well:

```reason
let add = (~first, ~second) => first + second;
let addFirst = add(~second=1);
addFirst(~first=2);
```

<div class="tips">
To take full advantage of partial application, it's recommended to place args that change most often at the end of the function, or to use labeled args.
</div>

Labeled arguments can also be optional. For that purpose, you just have to add a question mark as default value, like in the example below. This way, the corresponding argument is automatically provided as an option type, described earlier.

```reason
let addOptional = (~first, ~second=?) => first + switch(second) {
  | None => 0
  | Some(nb) => nb
};

let addDefault = (~first, ~second=0) => first + second
```

It would be possible to write an entire book about functional paradigms and Reason. A lot of concepts were deliberately bypassed in this section.

For more informations about functors, recursivity, mutual recursivity, I suggest you to take a look at [2ality - ReasonML Functions](http://2ality.com/2017/12/functions-reasonml.html) and [2ality - ReasonML Functors](http://2ality.com/2018/01/functors-reasonml.html). If you're interested about functional programming, I also advise you to read this [Marmelab blog post](https://marmelab.com/blog/2018/03/14/functional-programming-1-unit-of-code.html) by my colleague Thiery :)

## Setting Up a Reason Project

During my hack day, the first step was to setup the whole Reason stack inside [Docker](https://www.docker.com/), like we do for all our projects at Marmelab. Using Docker allows us to share projects across various environments with an easy installation.

To be honest, this setup experience was the worst I had in a long time. It took me about one hour to deal with many permission issues [[1]](https://github.com/BuckleScript/bucklescript/issues/2051) [[2]](https://github.com/BuckleScript/bucklescript/issues/1972). The recommended global install from the [official setup guide](https://reasonml.github.io/docs/en/global-installation.html) seems to be at the core of the problem.

Nevertheless, I'm pretty sure that the community will find solutions to make this first step easier. By the way, I'm [not the only one](https://blog.hasura.io/how-i-deployed-a-reasonml-react-app-with-docker-29dd2ce6de82) who struggled with that. Using the "node:6" docker image seems to do the job for the moment...

## Developer Experience First!

Once installed, the Reason developer experience is just *amazing*. The underlying BuckleScript compiler is quite fast, it builds [mosts projects](https://reasonml.github.io/blog/2017/09/08/messenger-50-reason.html) in less than 100ms, incrementally.

Moreover, the error reporter (based on [Merlin](https://github.com/ocaml/merlin)) is just perfect. It gives a detailed explanation of all possible mistakes thanks to the 100% type coverage of OCaml. Syntax errors are a little bit less clear but still give a good feedback. Here are two little examples to give you a preview of these powers.

<img src="https://marmelab.com/images/blog/reasonml/error1.png" />
<img src="https://marmelab.com/images/blog/reasonml/error2.png" />

## A React App In Seconds!

Because of its history, Reason maintains a strong relationship with React. In this regard, it is quite easy to setup a React project with Reason. I was able to confirm that during my reversi project.

[create-react-app](https://github.com/facebook/create-react-app) allows to focus on functionalities without worrying about toolchain configuration. So I took the decision to use it in association with [reason-scripts](https://github.com/reasonml-community/reason-scripts).

```
create-react-app reversi-reason --scripts-version reason-scripts
```

After the install step, I found myself with this familiar folder structure:

```
reversi-reason/
  README.md
  node_modules/
  package.json
  bsconfig.json
  .gitignore
  public/
    favicon.ico
    index.html
  src/
    index.re
    index.css
    app.re
    app.css
    logo.svg
```

The only difference with classic JS projects are files with a `.re` extension (which are, as you probably guessed, Reason files), and the `bsconfig.json` file, which is the BuckleScript configuration.

```json
{
  "name": "reversi-reason",
  "sources": [
    "src"
  ],
  "bs-dependencies": [
    "reason-react",
    "bs-jest"
  ],
  "reason": {
    "react-jsx": 2
  },
  "bsc-flags": [
    "-bs-super-errors"
  ],
  "refmt": 3
}
```

The BuckleScript configuration is a kind of mix between a linter config (like [.eslintrc](https://eslint.org/docs/user-guide/configuring)), and a compiler config (like [.babelrc](https://babeljs.io/docs/usage/babelrc/)). It's quite normal because BuckleScript fulfills these 2 missions.

## Domain Driven Design Made Easy

When I start a fresh new project, I always try to define the [ubiquitous language](https://martinfowler.com/bliki/UbiquitousLanguage.html) and the associated [domain objects](https://en.wikipedia.org/wiki/Domain-driven_design) before starting to code. For this project, I already knew my domain, because the reversi game is my favorite project to learn a new language, and I've already written a lot of code around it.

So, my domain objects are the following: **Game**, **Player**, **Board** and **Cell**. My first step was to create one [module](https://reasonml.github.io/docs/en/module.html) per object, with the associated test file. You can see them find them in [the reversi-reason Github repository](https://github.com/marmelab/reversi-reason/tree/master/src)!

```
src/
├── app.re
├── app_test.re
├── board.re
├── board_test.re
├── cell.re
├── cell_test.re
├── game.re
├── game_test.re
├── index.css
├── index.re
├── player.re
└── player_test.re
```

In OCaml / Reason, every file maps to a module; this built-in capability empowers most projects with an **out of the box Domain Driven Design architecture** and a strong expressivity.

There's no need for `require`, `use`, or `import` to use a module in Reason. Just call the module directly. This way, all the domain objects I talked before are automatically available through their names.

It's also possible to manually create modules using the `module` keyword. So, you can nest and access them using the dot notation (eg: `MyModuleFile.MyModule.MySubModule.myFunction`).

```reason
/* MyModuleFile.re */
module MyModule = {
  module MySubModule = {
    let myFunction = () => "hello";
  };
};

/* ... in another file ... */

let message = MyModuleFile.MyModule.MySubModule.myFunction;
```

In fact, you don't have to use the dot notation every time you want to access a value in a module. The Module definition can be opened both locally and globally to avoid this repetition.

An example "local" opening is the `applyCellClick` function below. The `Board.({ ... })` call exposes `applyCellChange` and `getCountForColor` from the `Board` module without having to repeat the module name.

```reason
/* game.re */
let applyCellClick = (game, x, y) => Board.({
    let color = Some(currentPlayer(game).color);
    let board = applyCellChange(game.board, { x, y, color });

    switch(getCountForColor(board, None)) {
        | 0 => { ...game, finished: true }
        | _ => switchPlayer({ ...game, board })
    };
});
```

This "local" opening could have been replaced by a "global" opening at the top of the `Game` module. Nevertheless, using global open [is not advised](https://reasonml.github.io/docs/en/module.html#open-ing-a-module) and must be used sparingly because it can break reasoning.

```reason
/* game.re */
open Board;

let applyCellClick = (game, x, y) => {
    /* ... */
};
```

## An Imperative Way Out

Reason uses a lot of concepts that are not always easy to handle (recursivity, currying, ...). Fortunately, it isn't as strict as [Haskell](https://www.haskell.org/), and it makes it possible to use some imperative and unsafe code when needed. This pragmatic approach is well highlighted in the Reason website.

> Reason has great traditional imperative & mutative programming capabilities. You should use these features sparingly, but sometimes they allow your code to be more performant and written in a more familiar pattern.

Here is one of the "ugliest" code snippets from my reversi-reason project. This function collects all flipped cells in a predefined direction. It's the most suitable example because it uses a lot of "legacy" (hear "not functional") capabilities that are allowed by Reason.

```reason
/* board.re */
let flippedCellsInDirection = (board, cell, (dirx, diry)) => {
    let cells = ref([]);
    let cursor = ref((cell.x + dirx, cell.y + diry));
    let break = ref(false);

    while (! break^) {
        cells := switch(cursor^) {
            | cursor when isOutOfBound(board, cursor) => break := true; []
            | (x, y) => switch(getCell(x, y, board.cells)) {
                | None => break := true; []
                | color when (color == cell.color) => break := true; cells^
                | _ => {
                    cursor := (x + dirx, y + diry);
                    [{ x, y, color: cell.color }, ...cells^]
                }
            }
        };
    };

    cells^
};
```

When you look at this code, the first thing that stands out is the usage of the well-known `while` loop. Effectively, Reason ([as well as OCaml](https://realworldocaml.org/v1/en/html/imperative-programming-1.html#for-and-while-loops-1)) allows the usage of [imperative loops](https://reasonml.github.io/docs/en/imperative-loops.html).

Also, to be able to break a while loop, I had to use a mutable flag. In Reason, all variables are immutable by nature. To be able to mutate a value, I had to wrap it with a [`ref`](https://reasonml.github.io/docs/en/mutation.html) that acts like a box.

Afterward, to retrieve the underlying `ref` value, the postfix `^` operator is used. The truth is that `ref` is [just a syntatic sugar](https://reasonml.github.io/docs/en/mutation.html#tip-tricks) for a predefined mutable record type. [Test by yourself!](https://reasonml.github.io/en/try.html?reason=DYUwLgBAZg9jEF4IG8DGMB2YRYM4C4IBWAXwG4AoUSKASwDcRFo4A6dLHMXS2GdzNjzMAbGSA)

In the next sections, I'll try to cover how strong the link between Reason and React is. First, talking about [ReasonReact](https://reasonml.github.io/reason-react/), and then talking about the associated tests with [Enzyme](https://github.com/airbnb/enzyme).

## Built-in JSX support

Before going further, you should know that Reason natively includes [JSX support](https://reasonml.github.io/docs/en/jsx.html). In fact, JSX only acts as a syntaxic sugar which is translated to normal function calls wrapped into expressions.

JSX translates to a `make` function call on the same module name as the JSX tag:

```jsx
<MyComponent foo={bar} />
```

Becomes

```reason
([@JSX] MyComponent.make(~foo=bar, ~children=[], ()));
```

That's why it's necessary to properly name modules. If you wish, you can still create multiple components in the same file thanks to [nested modules](https://reasonml.github.io/docs/en/module.html).

The Reason JSX syntax is not exactly the same as the JavaScript one. Indeed, there's no props spread but children spread. i.e. you can't do `<Foo {...bar} />` but you can do `<Foo> ...baz </Foo>`. 

## ReasonReact As Cornerstone

How to create React components in Reson? Here is an example:

```reason
/* player.re */

let component = ReasonReact.statelessComponent("Player");

let make = (~player, _children) => {
    ...component,
    render: (_self) => 
        <div className=("player")>
            (stringToElement(player.name))
        </div>
};
```

I created the component template in combination with the `statelessComponent` function from the [ReasonReact](https://reasonml.github.io/reason-react/) module. Spreading `...component` is a bit like saying my component "inherits" from `statelessComponent`, except that
 [class components](https://reactjs.org/docs/react-component.html) don't exist in Reason.

The `"Player"` string passed to `statelessComponent` primarily acts as a debug marker, it's the ReactJS equivalent of `displayName`.

## Redux-Like Components!

While the `statelessComponent` acts as a functional component mixin, there's also another special ReasonReact function called `reducerComponent`. This function allows to directly include a "state machine"-like architecture into our components.

<img src="https://marmelab.com/images/blog/reasonml/redux.png"/>

Using this component requires to define an `initialState` and a `reducer` function, which contain all the state manipulation logic. Those who have already used [redux](https://redux.js.org/) will certainly recognize this pattern.

```reason
/* game.re */

/* ... action type, state type and reducer ... */

let component = ReasonReact.reducerComponent("Game");

let make = (~game, _children) => {
  ...component,
  initialState: () => { game, message: None },
  reducer,
  render: (self) => {
    let { game, message } = self.state;

    let messageElement = switch(message) {
        | None => nullElement
        | Some(message) => stringToElement(message)
    };

    <div className="game">
        (messageElement)
        <Board
            board=game.board
            onCellClick={(x, y) => self.send(Click(x, y))}
        />
        /* ... */
    </div>
  }
};
```

In combination with the `reducerComponent`, it is usual to define 2 types:

* One type for the actions (represented as a variant), and
* One type for the state (represented as a record)

This way, Reason is able to infer by itself the `initialState` type. The `action` type is used to represent actions which can then be pattern-matched in the reducer function.

```reason
/* game.re */

type action = Click(int, int) | Restart;

type state = { game, message: option(string) };

let reducer = (action, state) => switch (action) {
    | Restart => ReasonReact.SideEffects(locationReload)
    | Click(x, y) => switch(applyCellClick(state.game, x, y)) {
        | game => ReasonReact.Update({
            game,
            message: None
        })
        | exception Board.InvalidMove => ReasonReact.Update({
            ...state,
            message: Some("Invalid Move")
        })
        | exception InsolubleGame(game) => ReasonReact.Update({
            game,
            message: Some("No One Can Play")
        })
        | exception CantSwitchPlayer(game) => ReasonReact.Update({
            game,
            message: Some("Opponent can't play, play again!")
        })
    }
};

/* ... react component ... */
```

According to the Reason philosophy, the reducer must be pure. Also using a pure function makes the code much more testable and easier to read. Only 4 distinct values can be returned:

* `ReasonReact.NoUpdate`: don't update state
* `ReasonReact.Update`: update state
* `ReasonReact.SideEffects`: don't update state but trigger a side effect
* `ReasonReact.UpdateWithSideEffects`: update state and trigger a side effect

## A Rigorous Interoperability

Reason allows to communicate with other languages thanks to [Externals](https://reasonml.github.io/docs/en/external.html) (also known as FFI or "interop"). Using "Externals" is the way to go to write safe, predictive, and reliable typed code between Reason and any other language.

<img src="https://marmelab.com/images/blog/reasonml/interop.png"/>

An Externals is a kind of typed contract / interface between the safe Reason world and the unsafe external world. It's this system that allows the [bs-jest](https://github.com/glennsl/bs-jest) and [bs-enzyme](https://github.com/rhysforyou/bs-enzyme) libraries that you'll find further to work.

Here is a simple example from the famous `alert()` function of JavaScript, which takes one arg and returns nothing (a.k.a. a "unit").

```reason
[@bs.val] external alert : string => unit = "alert";
alert("hello");
```

If you're an adventurous man, and you are using Reason with JavaScript, you can also use JS code through the [JS module](https://bucklescript.github.io/bucklescript/api/Js.html), or inject code directly.

```reason
/* Using the JS module */
Js.log("I'm logged via JS Module externals");

/* Direcly inject raw code */
[%bs.raw {| console.log("I'm logged via raw JS code"); |}];
```

A complete guide for JavaScript interop is available on [Reason](https://reasonml.github.io/docs/en/interop.html) and [Bucklescript](https://bucklescript.github.io/docs/en/intro-to-external.html) documentations.

## Unit Testing Reason Code

Under the hood, "create-react-app" uses [Jest](https://github.com/facebook/jest) as test runner thanks to the [bs-jest](https://github.com/glennsl/bs-jest) binding. Nothing special about it, the test architecture is almost the same as in JavaScript.

```reason
/* board_test.re */
open Jest;
open Expect;

describe("Board", () => {
    /* ... */

    describe("getCountForColor", () => {
        test("should return the number of cells of corresponding color", () => Board.({
            expect(getCountForColor(init(4, 4), Some(Cell.Black))) |> toBe(2);
            expect(getCountForColor(init(4, 4), Some(Cell.White))) |> toBe(2);
            expect(getCountForColor(init(4, 4), None)) |> toBe(12);
        }));
    });

    /* ... */
});
```

By the way, it's also possible to use [enzyme](https://github.com/airbnb/enzyme) to test components as in any other ReactJS project.

```reason
/* cell_test.re */
open Jest;
open Enzyme;
open Expect;

configureEnzyme(react_16_adapter());

describe("<Cell />", () => {
    test("should render a disk with the right identifier", () => {
        let test = (color, expectedClass) => {
            let wrapper = shallow(
                <Cell
                    color
                    onClick=((_) => ())
                />
            );

            expect(wrapper |> find(expectedClass) |> length) |> toBe(1);
        };

        test(Some(Cell.Black), ".cell.black");
        test(Some(Cell.White), ".cell.white");
        test(None, ".cell");
    });
});
```

## A Pragmatic Community

During development, I had plenty of questions about best practices. Faced with the lack of documentation, I went to the language [Discord](https://discord.gg/reasonml).

Despite a notable lack of online resources, Reason benefits from a large and reactive community (~200 people always connected). My questions didn't go unanswered more than 5 minutes.

Recently, I also discovered that the community has introduced a [centralized forum](https://reasonml.chat/) that appears to be very crowded and active. There are also [fabulous podcasts](https://reason.town/) that I've all listened to! Don't hesitate to listen to them, this initiative is rare enough to be highlighted.

Some of these quotes from other developers sound very relevant to me. They perfectly reflect the language's philosophy, which seems to be *pragmatism*.

> My philosophy is that **my time is more valuable than the computer’s time**, so if I write it in a way that I understand it, it’s OK. - jdeisenberg

> If this is a game that is going to be played by a human, then if evaluation of the board takes 2 milliseconds instead of 2 microseconds, will the person notice? Probably not. - jdeisenberg

A section from the "what and why?" of the language website confirms that this philosophy is not specific to the community, but to the language itself.

> **An eye for simplicity & pragmatism.** We allow opt-in side-effect, mutation and object for familiarity & interop, while keeping the rest of the language pure, immutable and functional.

Indeed, Reason is really a pragmatic language, and I like it. Moreover, this principle is consistent with [agility](https://marmelab.com/blog/2017/09/29/project-initialization.html), which we practice on every project at marmelab.

## Is This Ready To Use ?

Yes, it is ready to use in production! Reason is supported and [used by Facebook](https://reasonml.github.io/blog/2017/09/08/messenger-50-reason.html) everyday on big projects. This way, I think you can fairly trust it.

Moreover, Reason is a **very stable programming language**, it results from **decades of research** and compiler engineering from the OCaml language. Its interoperability capabilities give to Reason the **ability to be integrated** into any existing JavaScript project incrementally, so why wait?

On my side, there's no doubt that I would like to develop with Reason again. During this project, I've never felt stuck, **everything is designed to produce clean code, with pragmatic alternatives** in case of difficulty! The developer experience is just awesome!

To finish, its **active community** and **cross-platform capabilities** make me believe that Reason still has some beautiful days ahead. So, don't pass by it! And so, using types saves kittens, don't forget that!

<div class="tips">
You can test Reason without setting up a complete stack thanks to <a href="https://reasonml.github.io/en/try.html">the online compiler</a> which is very complete and impressively fast!
</div>

If you want to read more on the subject by other authors, I recommend the following:

* [What is ReasonML? (2ality.com - JavaScript and more)](http://2ality.com/2017/11/about-reasonml.html)
* [Exploring ReasonML And Functional Programming (reasonmlhub.com)](http://reasonmlhub.com/exploring-reasonml/)
* [JS Interop / Cross-platform Reason (jaredforsyth.com - Jared Forsyth Blog)](https://jaredforsyth.com/tags/reason/)
* [ReasonML Toolchain (khoanguyen.me - Khoa Nguyen Blog)](https://khoanguyen.me/reasonml-toolchain/)