ReasonMLは新しい言語ではありません。実は言語でもありません。OCaml の構文です。2016 年に Jordan Walke(React の開発者)に作成されました。OCaml のおかげで TypeScript より丈夫なタイプシステムがあり、JavaScript のような書き方で OCaml を書いたことがない方でもすぐ学べ、NPM・Yarn でもパッケージをインストールできます。ビルド時間が TypeScript より早く、Reason の JS アウトプットは Webpack より読みやすいです。OCaml の上で動いているので、プログラムのスタートアップが素早く、データが不変、ブラウザーの JS だけではなくネーティブコードもターゲットできます。
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
これ以上詳しく調べるなら公式サイトまでお越しください。
未来の構文
現在はバリバリで TypeScript を書いている方が多いと思いますが、ぜひ ReasonML も調べて欲しいです。Facebook に応援されているので、すぐサポートがなくなる言語ではありません。React の開発者に開発されたので、React のように深く考えらた言語だと思えばいいです。JS の経験があって、関数型プログラミングしたい方におすすめです。今は TypeScript のタイプシステムは不十分だと思う方にもおすすめです。
OCaml の上で動いていますが、ReasonML は JS/TS を使っている皆さんにアピールしたいので、これからも JS に親しむプログラマーたちを歓迎するように向けています。2020年7月には@dev
ブランチで新しい構文も出ています。その新しい構文はどんどん JS に近い書き方になっています。もちろん、互換性も考えられていています。.re
のファイル拡張子を使えば公式にサポートされたシンタックスに制限されますが、もし新しい構文を試してみたいなら、.res
のファイルが使えます。同じプロジェクトでも両方の構文が使えます。開発チームは今まで書いたコードを大事にしていますが、未来向きに ReasonML の将来を用意しています。
ぜひ使ってみてください!👋🏻