Elmやってみた

公開日:2019-05-05
最終更新:2019-05-05

GWの期間を利用してElmをやってみました。
その所感をまとめたいと思います。

作ったもの

shufflelm
なんてことはない、入力された内容をシャッフルして表示するだけのものです。
ソースはこちら
Elmの学習に2日、これの開発に2日で計4日ぐらいでした。

やろうと思った動機

だいぶ前から、関数型言語をなにか一つはやってみたいと思っていました。
GWというまとまった期間が取れるということと、旅行などのレジャー計画が諸々崩れ去ったということもあり、何か決めて取り組もう(&やりきろう)、と思い立ちました。
自分はWebフロントエンドが好きなので、AltJSであり、かつ関数型言語であるElmを見つけたとき、これだ!と思いましたw

Elmについて

Elmって何ぞや?みたいなことは、公式に書いてあるので割愛させて頂くとして、
どうやって学習したかとか、良いなと思った点とか、環境構築とかについて書きます。

学習方法

公式からもリンクがありますが、Elm Guideを一通り読みました。
嘘です。正確にはこれを読みました。
このガイドは非常に良くできており、その上さらに翻訳に関してもとても良くできていると思いました。読みやすい。
あえて言うなら、網羅性はそこまで無いので(たぶん読みやすさを重視し、意図してそうしている)、/= (not equalを表す)などの一部演算子や、let式の説明が無いので、ガイドを読み終わった後に別途Elmについてググると「えっこれ何?」みたいなシンタックスが出てくることがありました。

文法としては複雑なものは無く、The Elm Architectureについての学習が大半、という印象を受けました。
個人的には、ガイドは一番最後に出てくる「付録」部分が本編なように感じています。言語の書き方そのものというより、言語パラダイムを学ぶことで、今までと違うものの見方、考え方に触れることができました。

環境構築

参考にしたもの
https://qiita.com/kyasu1/items/44e67b8755f1adcfef67
https://mizchi.hatenablog.com/entry/2018/12/18/042834

構成としては、parcel + Elm ( + Tailwind CSS(後述))です。
まず、適当なフォルダで

yarn init  
yarn add parcel-bundler --dev  

した後、index.htmlindex.jsを用意(参考サイト参照)
Main.elmは一旦elm-architecture-tutorial/01-button.elmをコピーして作りました。
そして以下を実行してローカルで動くところまで完了。(実際はpackage.jsonに書きました)

parcel src/index.html --open  

あとは.gitignoreをよしなにするぐらい。

parcel、ちゃんとwebpackやってからにしよう・・・とずっと避けてきたのですが、今回は環境構築で手間取りたくなかったので、我慢して使いました。(結果、爆速で環境構築ができたので良しとしています)

shufflelmの開発について

開発中に困ったこととか、感じたことを書きます。

format

elm-formatを泣く泣く入れました。
4タブインデントとか、関数の間を何故か2~3行空けるとか、自分の好みでないフォーマットだと分かっていたため最初は避けていました。
が、今までElmを書いたことなど一度も無いわけで、Elmコードの書き方のベストプラクティス的なものが分からず、

  • 括弧で改行する?しない?
  • カンマは文頭文末どっちに置く?

など、細かいところで迷う時間を減らしたいと思い、結局導入しました。

ちなみに、せめて2タブにさせてもらえませんかねぇ・・・?と調べていたら、、、
https://github.com/avh4/elm-format/issues/210
同じことを思う人はやはりいらっしゃるようでして・・・w

エラー

Elmのエラーメッセージはすごく丁寧ですね。エラー理由だけでなく、直し方の候補まで出してくれたり、公式へのリンクを付けてくれたり。
https://guide.elm-lang.org/webapps/structure.html (日本語: https://guide.elm-lang.jp/webapps/structure.html) において、

This works because the compiler makes it really easy to do huge refactors.

と言っているだけのことはあるな、と思いました。

そんな中で、elm: Map.!: given key is not an element in the mapという謎のエラーにハマることがありました。
類似の現象にあっている人は結構居るようで、どうやらelm-compilerのバグらしいです。

  • デバッグモードがONになっている
  • Arrayを含むModelである

ときに起こるらしく、Arrayを使っていたため、全てListに変えたところ、エラーが起こらなくなりました。
だいぶ雑な対処方法で、結局エラーが起きていた理由もなんだか腑に落ちない感じなのですが・・・。

参考
https://qiita.com/hibohiboo/items/95490c26d33634546a80
https://qiita.com/kyasu1/items/44e67b8755f1adcfef67

乱数

ガイドを読んでも、初めは「なんでいちいちGeneratorを作らないといけないの」「乱数作るだけなのになんでBrowser.sandboxからBrowser.elementにしなきゃなの」という気にしかならなかったのですが、
Elmは言語レベルで、関数は、全く同じ引数を与えたら、全く同じ値を返すことを保証しているため、関数の中に副作用を起こすコードを書くことはできません。
そのため、呼び出すたびに値が変わる乱数などの副作用がある処理は、Elmコードの外で行わせる必要があります。
Elmコード内では、

  • 乱数を生成する方法(Generator)
  • どこかで生成されてきた乱数値(Msg)

だけを知っていればよい、というわけですね。
読むだけでなく、実際に自分でコードを書く経験を通して、やっと理解することができました。

後にこの「同じ関数同じ引数なら同じ返り値」という仕組みが、仮想DOMの差分比較にも応用されていると知ることになろうとは・・・。
https://guide.elm-lang.jp/optimization/lazy.html

css

ここだけほぼElm関係ない話に・・・w

elm cssでググるとこんなのが出てきてウッとなってしまったので、「cssはElmの外に書いて、Elm内ではclass当てるだけにしよう」という発想に至りました。
そこで環境構築のときにも見た https://qiita.com/kyasu1/items/44e67b8755f1adcfef67 を思い出し、いい機会なのでTailwind CSSを使ってみました。(最初CDN経由で試していたのですが、最終的には結局記事に書いてあるままの方法で導入しました。@applyが使えなかった・・・。)

Tailwind CSSの所感としては、

  • it's not a UI kit.とある通り、コンポーネント的なものは全く用意されていません。そのため、用意されているclassを組み合わせて「オレオレコンポーネントclass」を作った上で、classをバシバシ当ててスタイルを作っていく形になります。bootstrapに似ている感覚もありますが、所謂「タグの中に書いてあるclassがめっちゃ多くて見にくいんだけど」状態は回避できます。(でも結局@applyの後ろにいくつclass書いてるんだお前状態になります)
  • とにかくcssを書きたくない、けどcssフレームワーク使うとオリジナリティが出せなくて嫌だ、というワガママさんにフィットしそう
  • これを使って大きめのサイト構築をしようとした場合、コンポーネント分割のセンスが(多分)必要そうで、でもそのセンスあるならVueでSFC/ReactでCSS-in-JSとかに結局落ち着きそう
  • ちゃんと調べてないですがreset cssが内包されている?のは楽かも

VueやReact使ったナウいフロントエンドにできない、けど今後ナウくしていくためのせめてもの布石として、cssだけでもコンポーネント化しておきたい・・・!みたいなときに良いかもですね。
個人的にbootstrapよりは好きです。そしてtailwindを好きになる人の気持ちもよ〜〜〜く分かります。分かります・・・!、、、けど自分だったら自力で書く(CSS-in-JS)かな・・・。
どうやらv1.0.0に上がろうとしているみたいですので、今後どうなるか楽しみですね。

その他

ChangeItemValue index value ->とupdateを書いたとき、onInput (ChangeItemValue i)なんて書けるのかとドキドキしていましたが、書けました。
だったらChangeItemValue index -> value ->と書けて欲しいのは自分だけでしょうか。

得たもの

  • 関数のカリー化、部分適用についての理解
    • 今までは分かるような分からないような・・・な状態でしたが、完全に理解した状態になりました(フラグ)。
    • ちなみにElmにカリー化はありません。カリー化された関数しか無いからです。
  • model(Elmで管理する値(state))として持つものは何なのか?から始め、それをどうやって更新するか(update)→結果表示(view)という考え方の順番
    • 普段js書いているときはviewから考えが始まっていたなー、と気づくことができました。
  • 副作用が無い世界の良さ
    • ここで言う良さとは、どこで何が起きているか追いやすいことと、テスタブルであること、が挙げられます。
    • 多分これから他の言語でコードを書いていくときにも、「Elmのように、冪等性が担保された関数を書こう」という志に(今まで以上に)なる気がしています。

得られなかったもの

  • viewに関して、補助関数を切り出す単位やcssの組み合わせ方についてのベストプラクティス
  • モナド、高階関数、メモ化
    • キーワードだけ並べました。カリー化と同じく、分かるような分からないようなシリーズ。
    • 今回あえて深入りしすぎないようにした、というのもあるのですが・・・。いつかやっていきです。

これからのやっていき

実はshufflelmにはやろうと思って諦めた機能がいくつかありまして、、、

  • 画像も入力できるようにする
  • inputの中からN個選び、それをシャッフルする
  • シャッフル結果のクリップボードコピー

どれも簡単にはできなさそうだったので一旦見送りました。
Tailwind CSSも気力があったら剥がそうと考えており、これと併せて上記どれかをやるか、はたまたぜんぜん違う機能が追加されるか・・・は気が向いたら、って感じです。
例えばしばらく放置しておいて、Elmのバージョンが上がったときに戻ってくる、みたいなのもありかなと思っています。

Elmとしては、SPAの構築など、もう少し規模の大きいものを作ってみたいです。
今回は1ファイルで完結しましたが、規模が大きくなってきたときにElmがどうなるのかを感じてみたいです。(多分大きいものに向いていないのでは、という予想)

記事が少しでもいいなと思ったらクラップを送ってみよう!
27
+1

よく一緒に読まれている記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる

技術ブログをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

技術ブログを開設する

Qrunchでアウトプットをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

Markdownで書ける

ログ機能でアウトプットを加速

デザインのカスタマイズが可能

技術ブログ開設

ここから先はアカウント(ブログ)開設が必要です

英数字4文字以上
.qrunch.io
英数字6文字以上
ログインする