フラグ

先ほどのページでは、次のようなJavaSriptを実行することで、Elmのプログラムを起動する必要があることを説明しました。

var app = Elm.Main.init({
  node: document.getElementById('elm')
});

ここでは、JavaScriptからElmへと追加でデータを渡すことができます。たとえば、次のようにすれば、現在の時刻を渡すことができます。

var app = Elm.Main.init({
  node: document.getElementById('elm'),
  flags: Date.now()
});

この追加のデータはフラグ(flags)と呼ばれています。これにより、いろいろな種類のデータに基づいて、Elmプログラムをカスタマイズすることができるようになるのです。

Note: この追加のデータが『フラグ』と呼ばれているのは、それがコマンドラインフラグのようなものだからです。elm make src/Main.elmを実行するとき、--optimize--output=main.jsのようなフラグを追加して、その動作をカスタマイズすることができます。フラグもそれと似たようなものです。

フラグの操作

Elmでフラグを扱うには、JavaScriptから値を渡すだけでは不十分です。Elm側でそれを受け取る必要があるからです! Browser.element関数を使うと、initでフラグを受け取ることができるようになります。

element :
  { init : flags -> ( model, Cmd msg )
  , update : msg -> model -> ( model, Cmd msg )
  , subscriptions : model -> Subs msg
  , view : model -> Html msg
  }
  -> Program flags model msg

initflagという名前の引数を持っていることに注目してください。現在の時刻を渡したいということだったので、init関数を次のように書くといいでしょう。

init : Int -> ( Model, Cmd Msg )
init currentTime =
  ...

つまりこれは、JavaScriptから渡されたフラグの値を、即座にinitで受け取るようになったということです。initでは、その受け取ったフラグの値をモデルの中に格納したり、何かコマンドを実行することもできます。必要なことは何でもできるのです。

フラグの検証

しかし、Intをフラグとして受け取るようにinitを定義したにも関わらず、Elm.Main.init({ flags: "haha, what now?" })というように初期化しようとするような人がいたら、いったい何が起こるのでしょうか。

Elmはそのような場合に対してもチェックを行い、フラグの型が期待していた通りであることを保証してくれます。もしこのチェックがなければ、どんなデータでも渡すことができてしまい、Elm側では実行時エラーが起きてしまうでしょう!

フラグとして渡すことのできる型には、次のように様々な型があります。

フラグを厳密に制御できるように、常にJson.Decode.Valueを使うようにしている人もたくさんいます。どんな変な値であっても受け取り、それが予想外のデータであってもうまく修正することができるように、Elm側のコードでデコーダを書いているのです。

JSON.Decode.Value 以外の型をフラグとして渡す機能は、実はJSONデコーダーを使う方法が発明されるよりも前の時代に使われていたものです。 これらの型をフラグとして渡すには、いくつか注意しないといけないことがあります。次の例では、渡そうとしているフラグの型それぞれについて、いろいろなJavaScriptの値を渡すとそれぞれ何が起こるのかを示しています。

  • init : Int -> ...

    • 0 => 0
    • 7 => 7
    • 3.14 => error
    • 6.12 => error
  • init : Maybe Int -> ...

    • null => Nothing
    • 42 => Just 42
    • "hi" => error
  • init : { x : Float, y : Float } -> ...

    • { x: 3, y: 4, z: 50 } => { x = 3, y = 4 }
    • { x: 3, name: "tom" } => error
    • { x: 360, y: "why?" } => error
  • init : (String, Int) -> ...

    • ['tom',42] => ("Tom", 42)
    • ["sue",33] => ("Sue", 33)
    • ["bob","4"] => error
    • ['joe',9,9] => error

もしこのような変換がひとつでもうまくいかない場合は、JavaScript側でエラーが起こることに注意してください! Elmでは『フェイルファスト』(fail fast)の原則をとっています。Elmコード側でエラーを起こすのではなく、可能な限り早く問題を報告するということです。これはフラグにJson.Decode.Valueを使うのを好む人がいる理由のひとつにもなっています。JavaScript側でエラーが起きるより、デコーダでこの変な値を受け取ることで、何らかのフォールバックが実装されているのを保証するほうがいいということです。

results matching ""

    No results matching ""