わざわざ学ばなくてもいい言語ランキング1位の「Elm」をわざわざ学んでみる


平日ワイ

ワイ「優秀な若者たちが高速で仕事を終わらせてもうたから、ワイのやる事なくなってもうたで」
ワイ「弊社の10%ルール1を使って新しい言語のお勉強でもしてみよか」
ワイ「こないだ何かのランキングナンバーワンやったあの言語、なんやったっけな」
ワイ「・・・せや、Elmや」
ワイ「純粋関数型言語いうやつやな」
ワイ「ちょっとそのElmちゃんでも勉強してみよか」

とりあえずググる

ワイ「Elm、日本語・・・検索っと」
ワイ「おお、なんかとっても親切そうなサイトが見つかったで」
ワイ「・・・なるほどな〜」
ワイ「ElmいうんはJavaScriptにコンパイルできる言語なんやな」
ワイ「フロントエンドなワイにピッタリやないか」
ワイ「しかも、環境構築とかせんでも」
ワイ「Ellieいうサイト上で動かしてみることも出来るみたいや」

とりあえずHello World

ワイ「まずElmではどうやって文字とかタグを表示させんねやろ」
ワイ「ふむふむ」
ワイ「こうか?」

view model =
    div [ class "container" ] [ text "Hello World" ]

ワイ「おお、Hello Worldが表示されたで」
ワイ「しかし文法がよう分からへんで」

どういう文法

ワイ「view modelいうのは何や?」
ワイ「なになに、ええと」
ワイ「どうやらこれはviewという名前の関数を定義してるみたいや」
ワイ「ほんでmodelいうのが引数やな」
ワイ「このviewいう関数にはmodelいう引数が渡ってくる想定ですよ〜、っていう」
ワイ「仮引数ってやつや」

ワイ「ほなその下の」

div [ class "container" ] [ text "Hello World" ]

ワイ「↑これは何してんねん」
ワイ「ええと、なんや、このdivいうのも関数なんか」
ワイ「divという関数を使うとdivタグが生成される、いうイメージやな」
ワイ「ほえ〜」
ワイ「divいう関数に[ class "container" ][ text "Hello World" ]という」
ワイ「2つの引数を渡して実行してやる。すると・・・」
ワイ「第一引数の[ class "container" ]が、divタグの属性値、つまりクラスとかに変わって」
ワイ「第二引数の[ text "Hello World" ]が、divタグの中身になるんやな」
ワイ「pとかspanulliとかも関数として用意されとるみたいや」

ワイ「そういえば、戻り値を返すのにreturnとかは書かんくてもええんやな」
ワイ「今回でいうとdiv関数の結果が、自動的にview関数の戻り値になるみたいや」
ワイ「その関数の中で最後に評価した値が、自動的に戻り値になるいうことやな」

関数がコンポーネントみたいに使える

ワイ「タグの中に更にタグを書きたい場合は」

div [ class "container" ]
    [ p [] [ text "Hello" ]
    , p [] [ text "World" ]
    ]

ワイ「↑こう書けば」

<div class="container">
    <p>Hello</p>
    <p>World</p>
</div>

ワイ「↑こういうhtml要素たちを生成してくれるんやな」

ワイ「ビューを全部関数で書くなんてオモロイなあ」
ワイ「これを変数にでも入れておけば、それだけでコンポーネントとして使いまわせるやん」
ワイ「しかもただの変数や関数やから、プログラムの中に自然と溶け込ませることが出来るな」
ワイ「配列の分だけ回してコンポーネントを表示、とか」
ワイ「そんな時に便利そうや」

双方向バインディングでもしてみる

ワイ「ほな次はElmを使って、よくある双方向バインディングでもしてみよか」
ワイ「双方向バインディングいうんは」
ワイ「inputタグにテキストを入力すると、その値が即座にJS側に渡されて」
ワイ「ページの他の部分のDOMにもその値が反映される、みたいなやつや」
ワイ「Vue.jsとかでようやるやつやな」

ワイ「じゃあ今回は」

ユーザーがinputタグに数値を入力したら、
その数値が他のDOMにも表示される

ワイ「↑これを作ってみよか」

どんな情報を管理していくかをModelとして定義

ワイ「まずModelいう、状態を表す型を定義するんや」
ワイ「Elmは静的型付言語やからな」

ワイ「ほな、ユーザーが入力した数値はuserInputNumberいう名前で管理していこか」

type alias Model =
    { userInputNumber : Int
    }

ワイ「userInputNumber という整数の状態を管理していきますよ、と」

ワイ「ユーザーの入力によって、整数の値が変わったら」
ワイ「それを表示内容に反映させてやるためやな」

ワイ「ほんで、次はそのModelの初期状態をinitいう名前で定義するんや」

init : Model
init =
    { userinputnumber = 0
    }

ワイ「init : Modelいうのは」
ワイ「initという値はModel型の値ですよ、いう意味や」
ワイ「型注釈いうやつやな」

ワイ「あれ、エラーが出てもうた」

型の不一致
ヒント:レコードフィールドの間違いのようです。
たぶんuserinputnumberuserInputNumberであるべきでは?

ワイ「おお、userInputNumberキャメルケースのはずやのに」
ワイ「initの中では全部小文字で書いてたわ」
ワイ「ていうか、コンパイラがタイポを指摘してくれたで
ワイ「なんちゅう優しさや

ワイ「さっき定義したModelと、今書いたinitの中身が違ってると」
ワイ「ちゃんと怒ってくれるわけやな」

ワイ「そのためにはinitを定義するときにちゃんと型注釈を書いて」
ワイ「initという値は、Model型の値ですよ」
ワイ「って表明しとかなアカンけどな」

ワイ「型注釈をきちんと書いておくと、コードを読む人間にとっても」
ワイ「initという値はModel型の値なんやな!」
ワイ「ほなuserInputNumberいう値が中にあるはずやな!」
ワイ「とかって分かるし」
ワイ「もし間違った値を入れようとしたら」

Model型や言うてたのに、違う値を入れようとしてまっせ!

ワイ「ってコンパイラが怒ってくれんねん」
ワイ「型注釈を書くことで、コンパイラにもコードを読む人間にも注意を促せるわけやな」

ワイ「型注釈は」
ワイ「人間もコンパイラも読めるドキュメント
ワイ「って、ぴくすふぁんくさん(@pxfnc)も言うてたな」

ワイ「ほな、次はinputタグに入力した文字列をElm側で受け取る部分を書いていこか・・・」

〜続く〜

続編書いたで!

わざわざ学んでみたらElmのMaybe型が楽しかった

今回のコード

Ellieで見れるから好きにいじってみてや。


  1. 業務時間の10%(週4時間)を好きな研究・勉強に使っていいという制度