reasonml

ReasonML の環境構築 (3.0.4 対応)

基礎知識

  • Reason は独立した一つの言語ではありません。 OCaml の文法のスキンです。文法以外はすべて OCaml を使うと考えていいです。

  • Reason は BuckleScript というツールを使って JavaScript のコードを生成します。 BuckleScript は OCaml -> JavaScript のトランスパイラです (頻出する bs という単語は BuckleScript の略です) 。 Reason を使うには BuckleScript の詳細も (そのうち) 知る必要があります。

  • OCaml を学ぶ必要はあるかというと、すぐに知る必要が出てきます。文法に関してはしばらくの間は気にしなくてもいいと思いますが、何せ中身は完全に OCaml です。 Reason の標準ライブラリは OCaml のそれですし、サードパーティーのライブラリは OCaml で実装されたものも多いです。

  • 中身が OCaml なのでネイティブコードも吐けますが、今は期待しないほうがいいでしょう。もしネイティブアプリケーションを生成しても OCaml の制限をそのまま受けます。 Windows でのビルドは難しい、マルチコアに対応してない、など。コマンドラインツールを作りたいなら JavaScript のコードを実行可能ファイルに変換するツールを使うのもありかもしれません。

  • OCaml を普段使う人が Reason に乗り換える理由はあるかというと、まあないと思います。文法が複雑になってタイプ量が増えるだけですし。 OCaml 経験者がいないチームで開発するなら、 Reason のほうが文法的に抵抗がないかもしれません。

  • まだまだ発展途上で足りないものばかりです。実用的なプロジェクトでの採用はかなりの挑戦になるでしょう。

インストール

npm で配布されている ReasonML のパッケージ名は bs-platform です。パッケージにはコンパイラ以外にもフォーマッターなどの他のツールが含まれています。エディタのプラグインに必要になるため、グローバルにインストールするといいでしょう。

まず始めによくよく注意してもらいたいのですが、現時点では npm install bs-platform でインストール してはいけません。 npm で配布されているバージョンと最新のリリースバージョンが異なります。最新は 3.0.4 で、 npm のパッケージは 2.1.0 です。 3.x で大きく文法が変わったため、 2.x のツールではコンパイルもフォーマットもできません。のっけから罠です。

グローバルにインストールする方法 に従って、バイナリを指定してインストールします。

インストールしたくないが試してみたいという方は、 オンラインの実行環境 を利用するといいでしょう。

主なコマンドラインツール

主に次のツールがインストールされます。

  • bsb: コンパイラ。直接使わずに npm に任せましょう。

  • refmt: フォーマッター。エディタのプラグインで使えます。

  • rtop: 対話型環境。ちょっとしたコードを試したい場合にどうぞ。

エディタ

次のエディタ向けのプラグインが用意されています。

  • Visual Studio Code
  • Atom
  • Vim
  • Emacs
  • Sublime Text
  • IDEA

Visual Studio Code が推奨されています。このプラグインが最も早く最新バージョンに追従すると思います。私は節操がないので VSCode 始めました。

ユーザー設定の editor.formatOnSavereason.formatOnSavetrue を指定しておけば、ファイルの保存時にソースコードがフォーマットされます。

プロジェクトの生成

次のコマンドでプロジェクトのテンプレートを生成できます。詳しくは クイックスタート を参照してください。

$ bsb -init my-first-app -theme basic-reason

重要なファイル

  • .merlin: Merlin という OCaml のコード補完ツールが自動生成するファイルです。リポジトリに含める必要はありません。

  • bsconfig.json: BuckleScript の設定ファイルです。ビルド設定も含むため、わりと編集することになります。

ソースコードのサブディレクトリについて

Reason では「ファイル=モジュール」です。 foo.reFoo.re であれば Foo モジュールとして使えます (ファイル名の先頭が小文字の場合は、モジュール名は大文字で開始します) 。

ソースコードをサブディレクトリに分ける場合、ディレクトリ名とモジュールパスは 関係ない ので注意しましょう。例えば Foo.re でも myproj/Foo.re でも (ついでに言えば foo.re でも myproj/foo.re でも) 、どちらも同じ Foo モジュールです。

コンパイル

npm run build で行います。コンパイラ (bsb) を手動で使う必要はありません。

ビルドの設定

ビルドの設定は bsconfig.json に記述します。ファイル名からわかるように、基本的に BuckleScript に関する設定がほとんどです。

詳細は Configuration を参照してください。

警告

警告の設定は warnings に記述します。警告オプションの内容はまったく OCaml と同じで、指定方法も同じで独特です。ドキュメントも少ないです。ひとまずは OCaml の警告オプション が参考になるかもしれません。余裕があればまとめ直そうと思います。

"warnings": {
  "number": "A-4-9-40-42-44-45",
  "error": "A"
}

Reason に慣れてきたら上の警告オプションをセット

パッケージのリンク

bs.configbs-dependencies にパッケージ名を記述すると API を参照できるようになります。パッケージ名を package.json に記述しただけでは使えません。

サブディレクトリのソースファイルをビルドする

sources で指定するディレクトリの subdirstrue にすると、すべてのサブディレクトリが検索されます。デフォルトの設定ではサブディレクトリのソースファイルはビルド対象になりません。

"sources": [
  {
    "dir": "src",
    "subdirs": true
  }
],

JavaScript ファイルを lib/js に生成する

デフォルトの設定では、コンパイル後の JavaScript ファイルは Reason ファイルと同じディレクトリに生成されます。プロジェクトを作成すると用意される lib/js というディレクトリに生成したい場合は、 package-specs.in-source の値を false にします。

"package-specs": {
  "module": "commonjs",
  "in-source": false
}

JavaScript ファイルの拡張子を変更する

suffix で指定できます。デフォルトは .bs.js です。

"suffix": ".js",

ライブラリ

パッケージシステム

Reason Package Index があります。ほとんどが BuckleScript のバインディングです。

標準ライブラリ

悩みどころです。 Reason の標準ライブラリ は OCaml のそれで、 OCaml の標準ライブラリは貧弱さに定評があります。標準ライブラリについては 別の記事にも書きました (何の解決にもなってませんが) 。現行の OCaml 向けライブラリは OCaml に慣れてないとなかなかしんどいと思いますし、それなりの規模もありますし、そもそも JavaScript を考慮されたものではないので、私はとりあえず必要になった関数を オレオレなライブラリ にまとめてみてます。どんなにシンプルさを目標に掲げられたライブラリでもいずれは肥大化して下克上されるのが運命ですから、定期的に新しい基礎ライブラリが現れそうな気はします (Reason が広まればですけど...) 。

コーディングスタイル

Project Structure に多少記述があります。あとはフォーマッターに従えばいいと思います。ただし OCaml はデファクトスタンダードと言えるコーディングスタイルがなく、 OCaml のライブラリを扱うときは少し混乱するかもしれません。