情報アイランド

「情報を制する者は世界を制す」をモットーに様々な情報を提供することを目指すブログです。現在はプログラミング関連情報が多めですが、投資関連情報も取り扱っていきたいです。

F#入門(12)レコード型

レコード(record)とは、名前の付いた複数の値が一つになったものです。レコードを構成する一つ一つの名前付きの値をフィールド(field)と言います。

レコードは、タプルに名前の付いたものと考えると良いかもしれませんが、両者の間には幾つかの差異があります。

レコードを使用したい場合は、まずその型を宣言せねばなりません。型の宣言はtypeキーワードを使って以下のように行います。

type vec2 = { x:float; y:float }

この例では2次元ベクトルvec2型を定義しています。

typeキーワードの後に、型名、イコールと続け、最後に型の構成を指定します。フィールドは(フィールド名):(型名)という形で定義します。フィールド名は小文字から始まらなければなりません。複数のフィールドはセミコロンで区切り、全体を中括弧で囲みます。

vec2型の識別子を定義する場合はletキーワードを使って次の例のように書きます。

この例ではゼロベクトルを定義していますが、レコード型はそれを構成する値に名前が付いているので、値の順番に依存するタプルとは異なり、以下のどちらの書き方でも構わないことに注意してください。

また、識別子の定義時に型名を明示していないことにも注意してください。つまり、{ x = 0.0; y = 0.0 }のような書き方をするだけで型はF#によって自動的に推論されます。

let zero = { x = 0.0; y = 0.0 }

let zero = { y = 0.0; x = 0.0 }

このレコード型の識別子のフィールドの内容は所謂ドット記法で取得できます。

zero.x

zero.y

既存のレコードから新しいレコードを作る便利な方法があります。これはレコードが多くのフィールドを持つ時特に便利です。

例えば、先程定義した識別子zeroから新しいレコード{ x = 2.0; y = 0.0 }を作るには以下のようにします。

let a = { zero with x = 2.0 }

このように、中括弧の内部で、既存のレコードからどのフィールドを変更したレコードを作るかを、withキーワードを使ってその後に指定します。

この記法を使っても既存のレコードには何の影響も与えません。新しいレコード型の値が生成されます。

F#では、全く同じフィールド名と型名の組を持ったレコード型を宣言することができます。例えば次のようにです。

type type1 = { val1:int; val2:int; f:int -> int-> int }

type type2 = { val1:int; val2:int; f:int -> int-> int }

このような場合、このどちらかの型の値を定義する時、F#はどちらの型なのか推論できません。このような場合はnewキーワードとwithキーワードとandキーワードを使って以下のような方法で定義します(下の例にあまり意味はありません)。

let x =

    { new type1

        with val1 = 1

        and  val2 = 3

        and  f = (fun m n -> m + n) }

let y =

    { new type2

        with val1 = 1

        and  val2 = 5

        and  f = (fun m n -> m - n) }

このように、newキーワードの後に型名を入れることでまずどの型かを識別し、その後はwithキーワードとandキーワードを使ってフィールドの値を指定します。一番初めのフィールドはwithキーワード、それ以外はandキーワードを使って繋ぎます。

typeキーワードによる型の宣言は、andキーワードで複数の型を一緒に宣言することができます。

例えばB/S(の一部)を表す型は以下のように定義できます。

type BS        = { assets:Assets; liability:Liability; net_assets:NetAssets }

 and Assets    = { current:int; non_current:int }

 and Liability = { current:int; non_current:int }

 and NetAssets = { p_restricted:int; t_restricted:int; u_restricted:int }

前に宣言している型で、それより後に宣言している型が参照できていることに注意してください。これをこの順番のまま一つずつtypeキーワードを使って宣言しようとすると、未定義エラーになってしまいます。

pizyumi
プログラミング歴19年のベテランプログラマー。業務システム全般何でも作れます。現在はWeb系の技術を勉強中。
スポンサーリンク

-F#