ReasonMLは新しい言語ではありません。実は言語でもありません。OCaml の構文です。2016 年に Jordan Walke(React の開発者)に作成されました。OCaml のおかげで TypeScript より丈夫なタイプシステムがあり、JavaScript のような書き方で OCaml を書いたことがない方でもすぐ学べ、NPM・Yarn でもパッケージをインストールできます。ビルド時間が TypeScript より早く、Reason の JS アウトプットは Webpack より読みやすいです。OCaml の上で動いているので、プログラムのスタートアップが素早く、データが不変、ブラウザーの JS だけではなくネーティブコードもターゲットできます。

TypeScript vs ReasonML(英語)

ReasonML は Facebook に応援されています。ReasonML チームがオフィシャル Reason と React のバインドを開発しています。React は最初に作られた時に JS ではなく、スタンダード ML で書かれていました。もし React を書くなら、ReasonML は最高です

では、コードを見ましょう

最初は、簡単な JS を見てみましょうか?

変数

var firstName = "ブランドン";
let middleName = "リー";
const lastName = "ピットマン";

ReasonML だと…

let firstName = "ブランドン"
let middleName = "リー"
let lastName = "ピットマン"

ReasonML ではletしかありません。

記号列

JS と ReasonML の記号列はあまり変わらないので、スキップします。

配列

JS…

const numbers = [1, 2, 3];

ReasonML…

let numbers = [1,2,3] //これは配列ではなく、	連結リストです

// 配列にするなら…
let numbersArray = [|1,2,3|]

// タプルもある
type myName = { name: string }
let otherStuff = ("Brandon", 36, { name: "Brandon" })

配列と連結リストの内容は均質じゃないとだめですが、タプルは不均質でも大丈夫です。

オブジェクト

ReasonML(と OCaml)には関数型プログラミング言語の特徴が多いんですが、OCaml にオブジェクトもあります。けれども、ReasonML のドキュメントを読むと JS の経験者向けではありません。オブジェクトみたいなデータが必要な時に ReasonML のレコードがおすすめです。レコードとは?

type language = Reason | Ocaml | Typescript;

type person = {
	name: string;
	age: number;
	hometown: string;
	favoriteLanguage: language
}

let me = {
	name: "Brandon",
	age: 36,
	hometown: "Cincinnati, OH, USA",
	favoriteLanguage: Reason
}

レコードを定義する前にタイプも定義しなければなりません。TypeScript のタイプの書き方とそんなに変わりませんが、ReasonML のタイプは引数を受けることができます。私の誕生日を定義しましょう。

type threeThings('a) = ('a,'a,'a)
let myBirthdate: threeThings(int) = (1983, 8,31)

/* 上記のように使えますが、あとでそのタイプをもう一回使えます。*/

let fullName: threeThings(string) = ("Brandon", "Lee", "Pittman")

上記の ReasonML こんな JS にアウトプットされます。

// Generated by BUCKLESCRIPT, PLEASE EDIT WITH CARE
"use strict";

var myBirthdate = /* tuple */ [1983, 8, 31];

var fullName = /* tuple */ ["Brandon", "Lee", "Pittman"];

exports.myBirthdate = myBirthdate;
exports.fullName = fullName;
/* No side effect */

最後に出る JS は意外にきれいです。

if 文

JS と ReasonML のif文の書き方はそんなに変わりませんが、使い方が一つの大きい違いがあります。ReasonML のif文では最後の式がリターン値になります。下記の例を見てください。

let number = 1;

/* Unicodeを使うなら、下記の{j|...|j}を使わないといけない */
let result =
  if (number > 0) {
    {j|ゼロより大きい|j};
  } else {
    {j|1より少ない|j};
  };
/* resultは「ゼロより大きい」になる */

あとif文を書くとelseを絶対に書かないといけません。

Null と undefined

ReasonML にはnull又はundefinedというコンセプトはありません。その2つがないので、JS でよく起こるエラーに襲われません。もしnullみたいの値を使わないといけない時にはどうしましょうか?「パターンマッチング」を使います!ReasonML ではswitchをよく使うんですが、JS のswitchより力強いです。こういう風に使えます。

let author = Some("Brandon");

switch (author) {
| Some("Brandon") => Js.log("Hello there, Brandon.")
| Some(string) => Js.log("Welcome, " ++ string ++ "!")
| None => Js.log({j|We have no author. 😞|j})
};

きれいですね?JS のアウトプットはこんなものです。

var author = "Brandon";

if (author !== undefined) {
  if (author === "Brandon") {
    console.log("Hello there, Brandon.");
  } else {
    console.log("Welcome, " + (author + "!"));
  }
} else {
  console.log("We have no author. 😞");
}

exports.author = author;

関数

ReasonML の関数は ES6 の arrow 関数に近いです。functionというキーワードがありません。ES6 の書き方とほぼ一緒に見えます。

type person = {name: string,  age: int};
let me = {name: "Brandon", age: 36};

let greet = ({name, age}) =>
  Js.log({j|Hello, $name. I see you're $age years old.|j});
/* Unicodeのような書き方で内挿もできます。*/

JS のアウトプットは…

function greet(param) {
  console.log(
    "Hello, " + param.name + ". I see you're " + param.age + " years old."
  );
}

var me = {
  name: "Brandon",
  age: 36,
};

インストール

これで今回の簡単な紹介を終わらせますが、ReasonML を使いたいなら、どうすればいいでしょうか?下記の5ステップで初 ReasonML をコンパイルできます。アウトプットされる JS を既にある JavaScript 又は TypeScript のプロジェクトの中でもすぐ実装できます。

npm install -g bs-platform
bsb -init my-new-project -theme basic-reason
cd my-new-project
npm run build
node src/Demo.bs.js

これ以上詳しく調べるなら公式サイトまでお越しください。

ReasonML のオフィシャルサイト

未来の構文

現在はバリバリで TypeScript を書いている方が多いと思いますが、ぜひ ReasonML も調べて欲しいです。Facebook に応援されているので、すぐサポートがなくなる言語ではありません。React の開発者に開発されたので、React のように深く考えらた言語だと思えばいいです。JS の経験があって、関数型プログラミングしたい方におすすめです。今は TypeScript のタイプシステムは不十分だと思う方にもおすすめです。

OCaml の上で動いていますが、ReasonML は JS/TS を使っている皆さんにアピールしたいので、これからも JS に親しむプログラマーたちを歓迎するように向けています。2020年7月には@devブランチで新しい構文も出ています。その新しい構文はどんどん JS に近い書き方になっています。もちろん、互換性も考えられていています。.reのファイル拡張子を使えば公式にサポートされたシンタックスに制限されますが、もし新しい構文を試してみたいなら、.resのファイルが使えます。同じプロジェクトでも両方の構文が使えます。開発チームは今まで書いたコードを大事にしていますが、未来向きに ReasonML の将来を用意しています。

ぜひ使ってみてください!👋🏻