Elm Language
データの収集:タプル、レコード、および辞書
サーチ…
タプル
タプルは、任意の型の値の順序付きリストです。
(True, "Hello!", 42)
タプルの構造を変更したり、値を更新することは不可能です。
Elmのタプルは基本データ型とみなされます。つまり、タプルを使用するためにモジュールをインポートする必要はありません。
値へのアクセス
基本モジュールには( a, b )パターンマッチングを使用せずに、長さが2のタプル( a, b )値にアクセスするための2つのヘルパー関数があります。
fst (True, "Hello!") -- True
snd (True, "Hello!") -- "Hello!"
より長い長さのタプルのアクセス値は、パターンマッチングによって行われます。
パターンマッチング
タプルはパターンマッチングと組み合わせて非常に便利です:
toggleFlag: (Sting, Bool) -> (Sting, Bool)
toggleFlag (name, flag) =
(name, not flag)
タプルに関する解説
タプルには、 comparableデータ型の値が7個未満です
辞書
ディクショナリはDictコアライブラリに実装されています。
固有のキーを値にマッピングする辞書。キーは、どのようなタイプでもかまいません。これには、Int、Float、Time、Char、String、およびタプルまたは同等のタイプのリストが含まれます。
挿入、削除、クエリ操作はすべてO(log n)時間かかる。
タプルとレコードとは異なり、辞書は構造を変えることができます。言い換えると、キーの追加と削除が可能です。
キーで値を更新することは可能です。
動的キーを使用して値にアクセスまたは更新することもできます。
値へのアクセス
Dict.get関数を使用して、ディクショナリから値を取得できます。
Dict.get型定義:
get : comparable -> Dict comparable v -> Maybe v
存在しないキーによって値を取得しようとする可能性があるため、常にMaybe v返します。
import Dict
initialUsers =
Dict.fromList [ (1, "John"), (2, "Brad") ]
getUserName id =
initialUsers
|> Dict.get id
|> Maybe.withDefault "Anonymous"
getUserName 2 -- "Brad"
getUserName 0 -- "Anonymous"
値の更新
辞書の更新操作は、 Maybe.mapを使用して実行されます。要求されたキーが存在しない可能性があるためです。
import Dict
initialUsers =
Dict.fromList [ (1, "John"), (2, "Brad") ]
updatedUsers =
Dict.update 1 (Maybe.map (\name -> name ++ " Johnson")) initialUsers
Maybe.withDefault "No user" (Dict.get 1 updatedUsers) -- "John Johnson"
記録
レコードは、キーと値のペアのセットです。
greeter =
{ isMorning: True
, greeting: "Good morning!"
}
存在しないキーで値にアクセスすることは不可能です。
Recordの構造を動的に変更することは不可能です。
レコードでは、定数キーで値を更新できるだけです。
値へのアクセス
潜在的な実行時エラーを防ぐために、動的キーを使用して値にアクセスすることはできません。
isMorningKeyName =
"isMorning "
greeter[isMorningKeyName] -- Compiler error
greeter.isMorning -- True
値にアクセスするための別の構文では、レコードをパイプしながら値を抽出することができます。
greeter
|> .greeting
|> (++) " Have a nice day!" -- "Good morning! Have a nice day!"
拡張型
場合によっては、パラメータのシグネチャで関数に渡すレコードタイプを制約することが必要な場合があります。レコード型を拡張すると、スーパータイプの概念が不要になります。次の例は、この概念をどのように実装できるかを示しています。
type alias Person =
{ name : String
}
type alias Animal =
{ name : String
}
peter : Person
peter =
{ name = "Peter" }
dog : Animal
dog =
{ name = "Dog" }
getName : { a | name : String } -> String
getName livingThing =
livingThing.name
bothNames : String
bothNames =
getName peter ++ " " ++ getName dog
レコードをさらに伸ばして、次のようなことをすることもできます:
type alias Named a = { a | name : String }
type alias Totalled a = { a | total : Int }
totallyNamed : Named ( Totalled { age : Int })
totallyNamed =
{ name = "Peter Pan"
, total = 1337
, age = 14
}
これらの部分型を関数に渡す方法があります:
changeName : Named a -> String -> Named a
changeName a newName =
{ a | name = newName }
cptHook = changeName totallyNamed "Cpt. Hook" |> Debug.log "who?"
値の更新
Elmには、レコードの更新に関する特別な構文があります。
model =
{ id: 1
, score: 0
, name: "John Doe"
}
update model =
{ model
| score = model.score + 100
| name = "John Johnson"
}