ヤギの人の一覧のViewを自在に操る elm-referenceを読んできてね
概要
- list viewでindexベースで要素を更新するのは煩雑
- Mutable なプログラミング言語の「参照」があれば解決する
- elm-referenceはthis(現在注目している値)とroot(大元の値)の概念を用いて値に注目しつつ元の値を復元することで解決する
- 今回提案するselect-listでも値に注目しつつ、大元の値(Listに限定)を復元することで解決する
ということで 🎉🎉🎉I have just published miyamoen/select-list!🎉🎉🎉
モチベーション
immutable data structureでtreeをいい感じに更新するZipperっていうものがあります
このselect-listはzipperのlist版です。
elm-referenceの差別化点としてはList特化なのでその分Listには使いやすい感じになってます(当者比
もちろん自分でも普段使いしてます。べんり(当者比
select-list
の基本操作
まずは型
type SelectList a
= SelectList (List a) a (List a)
2個目のa
の値が選択されている値(selected value)で、最初のList a
が選択値の前のList(list before)、3個目のList a
が選択値の後ろのList(list after)です
[ 1, 2, 3, 4, 5, 6, 7 ]
このリストを3を選択したSelectListに変換すると
([] :: 1 :: 2) 3 (4 :: 5 :: 6 :: 7 :: [])
こんな感じになります。before
は内部的にひっくり返ってるのでひっくり返して表示してます
これのフォーカスを右(after)に2個動かすと
([] :: 1 :: 2 :: 3 :: 4) 5 (6 :: 7 :: [])
こんな感じになります。before/afterなlistの先頭をはいだり足したりしながら手繰り寄せる感じですね。内部の話なんで本題ではないんですがこんな仕組みになってます
select-list
をつかって書き直してみる
一覧のViewを自在に操る elm-referenceは読みましたか?読みましたよね?いきなり例出しますよ?
type Msg
= ClickNumber (SelectList Int)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ClickNumber selectList ->
( { model
| nums =
SelectList.toList <|
SelectList.updateSelected ((+) 1) selectList
}
, Cmd.none
)
view : Model -> Html Msg
view model =
div [] <| SelectList.selectedMapForList renderRow model.nums
renderRow : SelectList Int -> Html Msg
renderRow selected =
div
[ Events.onClick (ClickNumber selected) ]
[ text <| String.fromInt <| SelectList.selected selected ]
elm-reference
とほぼ一緒です。Msgに渡すものがReference Int (List Int)
からSelectList Int
に代わったくらいです
そして一番大事なSelectList.selectedMapForList
の型ですが
selectedMapForList : (SelectList a -> b) -> List a -> List b
比べてみましょう
selectedMapForList : (SelectList a -> b) -> List a -> List b
unwrap : (Reference a x -> b) -> Reference (List a) x -> List b
indexedMap : (Int -> a -> b) -> List a -> List b
indexedMap
と比較するとindexの代わりにSelectList a
を渡しています
a
の値は渡していませんがSelectList
が選択している値がa
ということになります
また、型構造を上で見た通り全体の構造が分かるのでindexも取れます。まあふいんきでわかってもらえたと思うのであとはpackage document読んでください(型眺めてるほうがわかることない?)
もっと比較したい場合は…
ここからふいんき度上がります。
elm-reference
のほうがいい点
-
Reference (List a) x
のxで大本の構造まで一発で戻せそう-
select-list
ではlistまでしか戻せないので
-
- list以外にも使える抽象
- exmapleにはtreeが用意されています
- 一方わたしはtree用のpackageも用意した
- exmapleにはtreeが用意されています
select-list
のほうがいい点
- List特化
- indexとか他の要素へもアクセスできる
- 選択している要素を上下に動かすとか要素の挿入とか削除とかのAPIを用意している
-
elm-reference
のexampleで上下移動と削除の例があるんですがちょっとわたしには実装が難しすぎました
-
結局自分で使うのにちょうどいいのを追求していく感じで作ってます
宣伝
深刻なレビュアー不足なので助けて