レコード

レコードとはいくつかの値に名前を付けてまとめて扱えるようにしたデータ。構造体のようなもの。名前と値をあわせてフィールド,名前をフィールド名と呼ぶ。

新しいレコードの型を宣言するには type 宣言を使う。

# type student = {name : string; id : int};;
type student = { name : string; id : int; }

name と id がフィールド名でそれぞれの値の型が string と int だ。

レコードを作るには次のようにする。フィールドの順番は入れ替わってもok。

# let st1 = {name = "Taro"; id = 123};;
val st1 : student = {name = "Taro"; id = 123}
# let st2 = {id = 51; name = "Ichiro"};;
val st2 : student = {name = "Ichiro"; id = 51}

また,すでにあるレコードと一部だけが違うレコードを作る方法もある。

# let st3 = {st1 with id = 456};;
val st3 : student = {name = "Taro"; id = 456}

st1 のフィールドを書き換えるわけではないことに注意。

# st1;;
- : student = {name = "Taro"; id = 123}

レコードのフィールドを参照するにはドット記法が使える。

# st2.name;;
- : string = "Ichiro"
# st2.id;;
- : int = 51

また,パターンマッチングもできる。

# let string_of_student {name = n; id = i} =
n ^ "'s ID is " ^ string_of_int i
;;
val string_of_student : student -> string = <fun>
# string_of_student st2;;
- : string = "Ichiro's ID is 51"

パターンにはすべてのフィールドを列挙する必要はなく,一部でもいい。

# let name_of_student {name = n} = n ;;
val name_of_student : student -> string = <fun>
# name_of_student st1;;
- : string = "Taro"

レコードのフィールド名は重ならないように

レコードの型を宣言するときの注意。既存の型と同じフィールド名を使ってしまうと,先に宣言した型のフィールド名が使えなくなってしまう。たとえば前エントリの student とその値が存在している状態で:

# type student = {name : string; id : int};;
type student = { name : string; id : int; }
# let st1 = {name = "Taro"; id = 123};;
val st1 : student = {name = "Taro"; id = 123}
# let st2 = {id = 51; name = "Ichiro"};;
val st2 : student = {name = "Ichiro"; id = 51}

新しいレコードの型を宣言する。フィールド名 name が重なっている。

# type foo = {name : bool};;
type foo = { name : bool; }

すると,name は foo のフィールド名としては使えるけど,student のフィールド名としては使えなくなってしまう。

# let f1 = {name = true};;
val f1 : foo = {name = true}
# let st4 = {name = "Daisuke"; id = 16};;
Characters 18-27:
let st4 = {name = "Daisuke"; id = 16};;
^^^^^^^^^
This expression has type string but is here used with type bool

アクセスもできない。

# st2.name;;
Characters 0-3:
st2.name;;
^^^
This expression has type student but is here used with type foo

f1 のフィールドにはアクセスできる。

# f1.name;;
- : bool = true