- Elm Advent Calendar 2016 - Adventar 10日目
- Elmの勉強の記録
- 今回は読書ノート
Chapter 4: Taking to Servers
- Richard Feldman, Elm in Action MEAP V03, pp.88-119
- 30ページくらいあるうちの今回は1/3くらい
- 他は、http通信と副作用、JSONデコードなどが話題としてあるがそれは11日目以降で
学んだこと、目に留まった箇所
Modelの型定義をMaybe
を使って書き直す
アプリデータはサーバーから取ってくるようにすると、この型定義はまずくなる
type alias Photo =
{ url : String }
type alias Model =
{ photos : List Photo
, selectedUrl : String
, chosenSize : ThumbnailSize
}
これを書き直す
-
Photo
型はこのままでokなのは、必ずメンバーを含むという型ではないから - データがなければ、画像のurlも選択しようがないし、サイズも選び様が無い、ということを型定義に踏まえてく
type alias Model =
{ photos : List Photo
, selectedUrl : Maybe String
, loadingError : Maybe String
, chosenSize : ThumbnailSize
}
モデルのフィールドを取り出す、簡潔な書き方
無名関数作って冗長にやってたところをスッキリかける
-- これは、
\photo -> photo.url
-- こう書ける
.url
Maybe.map
Maybe a
型のa
がRecord
型でフィールドの値を取り出したい場合にスッキリ書ける
newSelectedUrl : Maybe String
newSelectedUrl =
case newSelectedPhoto of
Just photo ->
Just photo.url
Nothing ->
Nothing
Photo
型のurl
フィールドの値を取り出すために、Just a
のブランチでまた別のJust..
を返すという少し冗長な書き方をしてるときに、Maybe.map
つかうと
newSelectedUrl : Maybe String
newSelectedUrl =
Maybe.map (\photo -> photo.url) newSelectedPhoto
とスッキリ書ける
関数のネストとパイプ演算子、|>
ある戻り値を得るのに、複数の関数呼び出しをするような関数について読みやすくするために用意されてるのだと理解した
- パイプ演算子には、逆向き(
<|
)もあるが、こっちの意義というか使い所はわかってない
前に、「Elmでは関数の戻り値は1つだけで引数も1つだけ」でも書いたが、Elmの関数の引数は1つなので
padLeft : Int -> Char -> String -> String
String.padLeft 9 '.' "not"
は実際は
padLeft : Int -> (Char -> (String -> String))
(((String.padLeft 9) '.') "not")
というふうに複数の関数呼び出しを行ってるが、Elmでは、カッコを外せて、読みやすく書きやすくなってる
テクニカルには、左結合だから外せる、と説明されてる
The reason we can avoid writing the parenthesis is because function application associates to the left.
これは、使われる引数が左から並んでるバージョンだったが、逆のバージョンもある
newSelectedUrl : Maybe String
newSelectedUrl =
Maybe.map .url (Array.get index (Array.fromList model.photos))
のMaybe.map .url (Array.get index (Array.fromList model.photos))
は
-
Maybe.map
のとこで説明したnewSelectedPhoto
を(Array.get...)
と、インラインで書いてる -
Array.fromList model.photos
から、Maybe.map .url
へと右から順番に読まなくていけない - これを
String.padLeft 9 '.' "not"
同様に、左から右へと書くために使えるのが、パイプ演算子|>
newSelectedUrl : Maybe String
newSelectedUrl =
model.photos
|> Array.fromList
|> Array.get index
|> Maybe.map .url
-
[引数] |> [関数]
という構造に変換 - 右側の引数を左側の関数に渡して、関数呼び出し
-
Array.get index
やMaybe.map .url
やそれ自体引数を取った関数呼び出しだが、関数を返すので、[引数] |> [関数]
の構造に沿ってる - コンパイル時には、変換前のカッコのついた右から読むバージョンに変換されるらしいのでパフォーマンスのデメリットはない