@ML DAY #1 LT, 2018/03/31
- Yu Matsuzawa @acecss-company (github/scrapbox)
- 業務ではElixirの人。Elixirもいいぞ
- Twitter: @gada_twt "Gadaさん"で
- Blizzard社のゲーム好き。Diabloシリーズで育つ
- MMORPG"World of Warcraft"は今年で10年戦士
- DelighfulにreliableなWebAppを書ける言語
- ML-inspired syntax
- 静的型付け、Immutable data、JavaScriptにコンパイル
- The Elm Architecture
- 専用のPackage Ecosystem
- 本勉強会に参加している方には名前くらいは知られてるはず
- 私の使用経験はサイドプロジェクトで約1年ほど
- 昨晩から突貫で作ったので粗いですが、追々いじってます
- こんな形をしています
- すでに原稿内のコードがmasterのコードに立ち遅れていて申し訳ない、、
-- Main.elm
main : Program Never Model Msg
main =
Html.program
{ init = init
, update = update
, subscriptions = always Sub.none
, view = View.view
}
-- Main.elm
update : Msg -> Model -> ( Model, Cmd Msg )
update msg ({ index } as model) =
case msg of
NoOp ->
( model, Cmd.none )
ClientRes (Ok (GetMarkdownFile filename contents)) ->
( { model
| index = Dict.insert filename contents index
, current = Just ( filename, contents )
, cursor = 0
}
, Cmd.none
)
...
-- Type.elm
type Msg
= NoOp
| ClientRes (Result Http.Error Success)
| OpenFile String
| CursorTo Int
type Success
= GetMarkdownFile String (List String)
type alias Model =
{ index : Dict String (List String)
, current : Maybe ( String, List String )
, cursor : Int
}
-- View.elm
view : Model -> Html Msg
view model =
section [ class "section" ]
[ div [ class "container is-fluid is-fullhd" ]
[ div [ class "columns" ]
[ aside [ class "menu column is-2" ]
[ p [ class "menu-label" ] [ text "INDEX" ]
, ul [ class "menu-list" ] <|
List.map
(\filename ->
li []
[ a [ onClick (OpenFile filename) ]
[ text (String.dropRight 3 filename) ]
]
)
slideList
]
, div [ class "column is-10" ] [ rendered model ]
]
]
]
...
- SyntaxはHaskellからの強い影響
- ただし、バージョンを重ねるにつれてかなりdiverge
- Explicitnessを重視
- Tagged UnionとRecordを使って
Model
やMsg
を定義 - HTMLタグと対応した関数で文書構造を純粋な
view
関数として記述- elm-lang/virtual-domによる高速な描画
update
でアプリケーション内で発火されるMsg
に対する状態遷移をexhaustiveに記述Msg
の発火は「view
で定義したDOMから」「update
の返り値として連鎖的に」 「外部からsubscriptions
経由で」
- これが基本的なThe Elm Architecture(TEA)
- Elmではどんなアプリも全てこのアーキテクチャのもとに開発
- TEAでアプリケーションを開発するためのフレームワークが言語に同梱されている
- すでに多くのフォロワーが生まれている
- ElmはHaskell/PureScriptと比較すると、型システムはかなり簡素
- Type classはありません
- 何かそれに変わるシステムが用意されているわけでもないので、関数overloadもできません
Maybe
やResult
などがありますが、統一されたmap
はなく、Maybe.map
やResult.map
を使います
- これを含め、言語機能の策定には「とにかくexplicitに、そして初学者に優しく」という方針が徹底して貫かれています
- コンパイラは充実したエラーメッセージやinstructionに溢れてます
- (黒魔術が存在しないわけでもないですが、)基本的にユーザが書くElmプログラムは全て純粋
- 非純粋な処理はすべてElm runtimeが非同期実行し、結果は型検査された安全な値として
Msg
にenvelopeされてupdate
にrouting- この処理実行単位を
Cmd
と呼び、Cmd
を構成する小単位がTask
- この処理実行単位を
- 非Elm界(≒JS界)との対話も基本的にすべてこの経路
- ユーザ独自にJS側で処理を記述したい場合は
port
という仕組みを利用、やはりCmd
とsubscriptions
によるインターフェイス - いわゆるFFIのような仕組み(Elm関数の内部動作をJSで直接実装)は、非推奨かつ次バージョンでは禁止の見込み
- ユーザ独自にJS側で処理を記述したい場合は
- とにかく安全!これでもかとSanitizeされた環境で純粋なプログラミングに徹するのみ
- 「コンパイラに優しく導かれる」という今までにないWebApp開発ができることは請け合い
- 公式いわく、**"zero-runtime exception"**を実現可能
- (とはいえこれは"zero-bug"というわけではないし、コンパイラバグもちょくちょくありますが)
- あまりに気持ちいいので、最近Elixirにも満足できなくなってきた
- Elm開発コアチームの人のセッションに、"Make the Back-End Team Jealous: Elm in Production"というタイトルがあったけど、まさにその心境
Elmは、
— Gadagarr (@gada_twt) February 21, 2018
・導入コスト: ゼロ (amortized;フレームワークがわかりやすいしコンパイラも親切、文法の不慣れさをも相殺する)
・メンテコスト: ゼロ (コンパイラが不可能な変更は拒絶する。壊せないものは壊れないからメンテフリー)
・心理コスト: ゼロ (amortized; 導入後の幸福によって相殺される)
- 懸念点、もちろんあります。プロダクトに使おうとする場合は十分にInformedな状態で判断しましょう
- サイドプロジェクト・個人開発からであれば何も心配なし。というか会う人だいたい全員に薦めてる
- 既存のアプリの一部分から使い始めることも可能だし、アプローチとしても推奨されている
- Elmはどんな人にオススメできないか - Qiita
- 個人的な印象でいくつかポイントを上げるなら:
- ボイラープレートの多い言語ではあります(Explicitness/Simplicityの裏返し)
- 言語コア周辺から離れるにつれてコード共有(ライブラリ化)がしづらくなる傾向があります
- そもそも新興言語でライブラリが少ない、というのも
- バージョンアップはかなり遅いです
- このあたり、質問ありましたらぜひ
- Elmについて、何か困ったら:
- 国内のコミュニティも育ってきてます!
- Connpass: elm_tokyo, elm-jp
- 直近ではElmハンズオン in 名古屋 - connpass募集中
- Discord
- Scrapbox
- Connpass: elm_tokyo, elm-jp
Thank You!