ElmとWebAssemblyで迷路生成Webアプリを作った話
はじめに
東京大学計数工学科は毎年物理工学科と一緒に五月祭で工学博覧会という企画を行っています。
今回、「アルゴリズム」を紹介するということで迷路生成アルゴリズムを展示しました。
そのためのwebアプリをElmとWebAssemblyで作って公開したので紹介します。
機能
お絵かきをして
格子グラフを作って(頂点をタップすると格子グラフが編集できます)
Submitすると迷路が出来ます。
そしてこの迷路にはスタートからゴールに至るルートが一つだけあって、
この迷路の答えは元の絵となります!
いろんな迷路を作ってみてください!
採用理由
Elm
ElmはUI作成に特化した言語、アーキテクチャです。
今まで自分はWebフロントを書いたことが全くありませんでした。ブラウザで実行できる以外に良い点が無さそうなJavaScript(偏見)を勉強するモチベも、技術の流れが早く数年後には廃れているであろう色々なフレームワーク(偏見)を勉強するモチベも全く湧かなかったのですが、ElmはJavaScriptを書かなくて済みそうで、かっこよさそうなのにそんなに流行っていなさそうだったので使ってみることにしました。
まあ純粋関数型言語って響きがカッコイイよね。
WebAssembly
迷路生成アルゴリズムはもともとC++で書いてありました。
五月祭当日はGoogle Compute Engineを借りてその上で実行する形を取っていたのですが、出来ればクライアント側で完結させたいです。そうするとお金も掛からないし、遅延も少なくなります。JavaScript等に書き直せば話は簡単ですが、JavaSciptのことはよく知りません。
WebAssemblyは、クライアント側で実行出来て、C/C++やRustからコンパイルして作ることが出来ます。
もともとのC++で作られたプログラムは標準入出力でやり取りをするだけであったので、それを一つの関数としてまとめました。
C++のSTL等にも普通に対応しており、既存のコードのIOの部分だけちょっといじればコードをそのまま流用できます。
感想
Elmは素晴らしい言語、アーキテクチャでした。JavaScriptの世界は闇の世界(偏見)だと思っているのですが、Elmは楽園(偏見)です。(ちなみに自分はElm以外のフレームワークに触ったことが無いので比較などは全く出来ません)
- 純粋関数型のおかげか、コンパイルが通ればほとんど実行時エラーを見ることはない
- Elm Architectureのおかげか、全く苦労することなく並行性を持ったプログラムが書ける
- 出来ることが適切に制限されているので、全体の構造を意識せず適当に継ぎ足しながら書いても全然崩壊しない
- UIに特化していることでHaskellのような理解にひと手間かかる概念がないのでスタートダッシュも楽々(例えばモナドとして抽象化出来る機能がいくつかあるが別に抽象化はしていない)
- Haskellなどでメモリ効率を意識したり色々なデータ構造を導入しようとすると初心者には厳しい領域に入るが(Haskellで例えばセグメント木をどう書けば良いのか自分にはよくわかりません)、WebのUIというのは通信とDOMの操作が重たいパートなのでそこまで効率を意識したコードを書く必要もないー>そういった苦労もあまりない
- JavaScriptの世界とElmの世界はPortで繋げることが出来るが、Elm側の世界が安全でしっかりしているのでJavascript側の世界がゆるゆるでもどうにかなる
Elmのおかげで非常に気楽にWebアプリを作ることが出来ました。
WebAssemblyも初めて使ってみましたが、期待通りの働きをしてくれました。感想としては
- C++で書いたコードをそのまま流用できるのが非常に嬉しい。
- 重たい処理をC++/Rustで書いてクライアント側で実行出来るのは便利。最適化やらソルバーやら画像処理やら複雑なアルゴリズムやらをクライアントサイドで実行したいならば一番良い選択肢なのでは無いか?
- 謎の実行時エラーを吐かれたときにデバッグがしにくい(良いツールを知らないだけかも?)ので既存のライブラリを流用するのではなく自分で書く時はRustのようなメモリ安全性が担保しやすい言語で書いたほうが良いのかも。
- Emscriptenはwasmとそれを実行するJavaScriptファイルを出力して、それを用いると非常に気軽にwasmを実行できる。パフォーマンスを重視するならば自分でfetchしたりするコードを書いたほうが良いのかも。
ちなみに、WebAssemblyはバイナリファイルにする前の中間表現としてS式(Lispに使われてるアレです)を用いているので、非常に読みやすいです。まともにアセンブリを読んだことがない人の戯言ですが、よく見るx86のアセンブリ等よりも断然読みやすいんじゃないんでしょうか
また、mallocのコストは重いのか軽いのか等細かいことはよく分かっていないので必要になったらまた勉強しようと思います。
まとめ
Elmは非常に便利でストレスなくWebアプリを作ることが出来ます。もしも重たい処理を実装したくなったり既存の資産を流用したくなったらメモリをちゃんとハンドリングする言語の中で自分が得意なもので書いてWebAssemblyにコンパイルすれば万事解決です
UIの部分をElmで書いて、重たい処理をWebAssemblyに任せるという分業はもしかしたら素晴らしいかもしれません。WebAssemblyの今後に期待です。
ちなみに今回始めてCSSを書いたんですが、CSSはよくわからなかったです。
なにはともあれ色々迷路を作って遊んでみてください!
ここまで読んでくださってありがとうございました!
ちなみにソースはここに置いてあります
https://github.com/tomabou/meyfes-front
ちょっとした注釈
ElmとJavascriptの間で情報をやり取りするにはFlagかPortを使うのが一般的だが、画面に描画していればJavascript側からDomをGetして中身を見ればElmの世界からJavaScriptの世界に情報を伝えられる。
今回のCanvasからグラフを生成するところではそれを用いた。