Help us understand the problem. What is going on with this article?

ReasonML雑感

More than 1 year has passed since last update.

ReasonML雑感

by soebosi
1 / 14

ReasonML

  • facebook製プログラミング言語
  • JavaScript、バイナリ両方にコンパイル可能
  • OCamlとJavaScriptのエコシステムが利用できる
  • 強力な型付けとイミュータブルが特徴
  • 2018/02/21 時点で最新バージョンは3.0.4

BuckleScript

  • OCamlのJavaScriptバックエンド
  • Bloomberg社製
  • ReasonMLはBuckleScriptに乗っかっている
  • 2018/02/21 時点で最新バージョンは2.2.0

アーキテクチャ

reason architecture
https://github.com/facebook/reason/tree/master/src より引用


構文

  • パターンマッチ
  • ファンクター(Module Functions)
  • パイプ演算子
module IntPairs = {
  type t = (int, int);
  let compare = ((x0, y0), (x1, y1)) => {
    switch (Pervasives.compare(x0, x1)) {
      | 0 => Pervasives.compare(y0, y1)
      | c => c
    }
  };
};

module PairsSet = Set.Make(IntPairs);

let m = PairsSet.(empty |> add((2, 3)) |> add((5, 7)) |> add((11, 13)));
Js.log(PairsSet.min_elt(m)); /* => [2, 3] */
  • これをコンパイルすると、

'use strict';

var $$Set = require("bs-platform/lib/js/set.js");
var Curry = require("bs-platform/lib/js/curry.js");
var Caml_obj = require("bs-platform/lib/js/caml_obj.js");

function compare(param, param$1) {
  var c = Caml_obj.caml_compare(param[0], param$1[0]);
  if (c !== 0) {
    return c;
  } else {
    return Caml_obj.caml_compare(param[1], param$1[1]);
  }
}

var IntPairs = /* module */[/* compare */compare];
var PairsSet = $$Set.Make(IntPairs);
var m = Curry._2(PairsSet[/* add */3], /* tuple */[
      11, 
      13  
    ], Curry._2(PairsSet[/* add */3], /* tuple */[
          5,  
          7   
        ], Curry._2(PairsSet[/* add */3], /* tuple */[
              2,  
              3   
            ], PairsSet[/* empty */0])));

console.log(Curry._1(PairsSet[/* min_elt */20], m));

exports.IntPairs = IntPairs;
exports.PairsSet = PairsSet;
exports.m = m;

レコード

  • イミュータブルなオブジェクト
/* ここの型宣言がないと型推論に失敗してコンパイルエラー */
type r = {
  a: int,
  b: int 
};

let r1 = { 
  a: 1,
  b: 2
};
let r2 = { 
  ...r1,
  a: 3
};

Js.log(r1.a); /* => 1 */
Js.log(r2.a); /* => 3 */

  • オブジェクトではなく、配列として出力される
  • イミュータブルという前提があるため最適化がうまく効いていそう
var r2 = /* record */[
  /* a */3,
  /* b */2
];

console.log(1);

console.log(3);

var r1 = /* record */[
  /* a */1,
  /* b */2
];

exports.r1 = r1; 
exports.r2 = r2; 

演算子の独自定義

let (<$>) = (a, b) => a + b;

Js.log(1 <$> 2); /* => 3 */

ReasonReact

  • ReactのReasonMLバインディング
  • Reduxも一部含む
  • Routerも一部含む

type action =
  | ChangePage(ReasonReact.reactElement);

type state = {
  page: ReasonReact.reactElement,
};

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

let make = (_children) => {
  ...component,
  initialState: () => {
    {page: <TopPage />} 
  },  
  reducer: (action, state) =>
    switch (action) {
    | ChangePage(page) => ReasonReact.Update({...state, page})
    },
  subscriptions: self => [
    Sub(
      () =>
        ReasonReact.Router.watchUrl(url =>
          switch(url.path) {
          | []                 => self.send(ChangePage(<TopPage />))
          | ["hello", message] => self.send(ChangePage(<HelloPage message=message />))
          | _                  => self.send(ChangePage(<ErrorPage />))
          }
        ),
      ReasonReact.Router.unwatchUrl
    )
  ],
  render: self => self.state.page
};

テスト

  • Jestが動くらしいが試せていない

コレクションライブラリ

  • Immutable.re
    • ReasonML純正ライブラリ
    • 実験段階。Immutable.jsのバインディングを利用するよう公式が言っている
    • githubのコミットも半年前ぐらいでストップ
  • rationale
    • Ramda.jsリスペクト
    • 最近作られたばかり
    • Haskellライクな独自演算子を定義

個人的に気になっているところ

  • JSXの構文に少し癖がある
    • テキストノードをそのままかけず、stringToElementという関数を呼ぶ必要がある
    • <div>ReasonReact.stringToElement("Hello")</div> とすると>の後ろにスペースがなく構文エラー
  • やっぱりOCaml知らないとつらそう
  • あまり流行ってない
  • ファイル === モジュールという考え方
    • ディレクトリ構造は無視されてフラットに外部ファイルが呼べてしまう
    • importみたいな構文なく、ファイル名をモジュール名として使ってアクセスできてしまう
soebosi
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away