レコード (計算機科学)
レコード (record) は構造体 (structure)、複合データ (compound data / composite data) とも呼ばれ、計算機科学では、基本的なデータ構造である。データベースまたはスプレッドシートのレコードは通常、「行」と呼ばれる。
レコードは、フィールドの集まりであり、通常は固定の数(と並び)のフィールドから成り、(配列と違って)各フィールドのデータ型は異なってよい。レコードのフィールドは、言語によってはメンバーあるいはメンバー変数と呼ばれることもある。オブジェクト指向プログラミングでは、インスタンス変数と呼ばれることもある。フィールドは要素と呼ばれることもあるが、これはコレクションの要素と混同される恐れがある。
たとえば、日付レコードDateは、数値型の年yearフィールド、数値型の月monthフィールド月は"Jan", "Feb", ...のような文字列で表現することも可能だが、英語圏でしか通用せず、また文字列は記憶容量を余計に必要とし、プログラミング言語によって実装形態も異なるため、レコード表現としては数値型のほうが好まれる。曜日 (day of week) に関しても、カレンダーから計算可能であるため、レコードのフィールドとして含むことは少ない。、数値型の日dayフィールドを含むレコードとして定義できる。人事レコードPersonnelには、名前name、給与salary、階級(等級)rankなどが含まれる。円レコードCircleには中心centerと半径radiusが含まれる。この場合、中心center自体は2次元座標のxとyを含む点レコードPointとして表すことができる。
「レコード型」は、そのような値と変数を記述するデータ型である。レコード型は、通常は、フィールド数が固定されており、各フィールドに名前があり、各フィールドの型が異なる場合があるところが、配列と異なる。
最新のコンピューター言語のほとんどでは、プログラマーはレコード型を定義できる。定義には、各フィールドのデータ型と、フィールドにアクセスできる識別子(名前またはラベル)の指定が含まれる。型理論では、直積型(タプル型; フィールド名なし)が単純であるため一般的に好まれるが、真のレコード型はSystem F-subなどの言語で研究されている。型理論のレコードには、データに加えて第一級関数型フィールドが含まれる場合があるため、オブジェクト指向プログラミングの多くの機能を表現できる。
レコードは、メインメモリや磁気テープやハードディスクなどの大容量記憶装置を含む任意の記憶媒体に存在させることができる。レコードは、ほとんどのデータ構造、特にリンクされたデータ構造の基本的なコンポーネントである。多くのは、論理レコードの配列として編成され、効率を上げるために、より大きな物理レコードまたはブロックにグループ化される。
関数またはプロシージャのパラメータは、多くの場合、レコード変数のフィールドと見なすことができる。また、その関数に渡された引数は、呼び出し時にその変数に割り当てられるレコード値と見なすことができる。また、プロシージャコールの実装によく使用されるコールスタックでは、各エントリはアクティベーションレコードあるいはコールフレームであり、これにはプロシージャパラメータとローカル変数、リターンアドレス、およびその他の内部フィールドが含まれている。
オブジェクト指向言語のオブジェクトは、基本的に、そのレコード自身の処理に特化したプロシージャを含むレコードである。非オブジェクト指向言語を拡張してオブジェクト指向化した言語(Simula系統のクラスベースオブジェクト指向言語)において、オブジェクト型は、レコード型を拡張したものであることが多い(C++やObject Pascalなど)。実際、ほとんどのオブジェクト指向言語では、レコードはオブジェクトの特殊なケースであり、オブジェクト指向機能を使用するオブジェクトとは対照的に、プレーンオールドデータ構造(PODS)またはパッシブデータ構造と呼ばれる。
レコードには、0個以上の「キー」が含まれる場合がある。キーは、識別子として機能するレコード内のフィールドまたはフィールドのセットである。一意のキーは、「主キー」または単に「レコードキー」と呼ばれる。たとえば、従業員ファイルに、従業員番号、名前、部門、給与が含まれるとする。従業員番号は組織内で一意であり、主キーとなる。記憶媒体とファイル構成によっては、従業員番号に「インデックス」が付けられ、検索を高速化するために別のファイルにも保存される。部門コードは一意ではない場合があるが、インデックスを付けることもできる。その場合、「セカンダリキー」または「代替キー」と見なされる。インデックスが作成されていない場合、特定の部門のすべての従業員のリストを作成するには、従業員ファイル全体をスキャンする必要がある。給与フィールドは通常、キーとして使用できない。インデックス作成は、ファイルを設計するときに考慮される1つの要素となる。
各フィールドの位置、型、名前を含む、新しいレコード型の宣言。
特定のレコード型を持つ変数と値の宣言。
指定されたフィールド値から、指定されたフィールド名を使用してレコード値を作成。
レコードの明示的な名前を持つフィールドの選択。
レコード変数へのレコード値の代入。
2つのレコードを比較して等しいことを確認。
レコードの標準ハッシュ値の計算。
レコード値からフィールドを選択すると、値が生成される。
一部の言語は、レコードのすべてのフィールド、または少なくとも参照できるフィールドを列挙する機能を提供する。この機能は、デバッガー、ガベージコレクター、シリアル化などの特定のサービスを実装するために必要となる。ある程度のポリモーフィズムが必要となる。
メモリ内のレコードの表現は、プログラミング言語によって異なる。通常、フィールドは、レコードタイプで宣言されているのと同じ順序で、メモリ内の連続した位置に格納される。これにより、2つ以上のフィールドが同じメモリワードに格納される可能性がある。実際、この機能は、単語の特定のビットにアクセスするためのシステムプログラミングでよく使用される。一方、ほとんどのコンパイラは、マシンによって課せられる配置の制約に準拠するために、プログラマからは見えない余白フィールドを追加する。たとえば、浮動小数点フィールドは1ワードを占める。
一部の言語では、フィールド(および場合によっては名前やタイプ)を指すアドレスの配列としてレコードを実装する。オブジェクト指向言語のオブジェクトは、特に複数クラスの継承を許可する言語では、かなり複雑な方法で実装される。
「自己定義レコード」は、レコード型を識別し、レコード内の情報を見つけるための情報を含むレコード型である。要素のオフセットが含まれる場合がある。したがって、要素は任意の順序で格納することも、省略しても良い。 あるいは、それぞれが要素識別子を含むレコードのさまざまな要素は、単純に任意の順序で互いに続けて配置される。
以下に、レコード定義の例を示す。
PL/I:
Algol 68:
mode date = struct (int year, int month, int day);
C:
Fortran:
Go:
Pascal:
Rust:
Haskell:
Julia:
Standard ML:
COBOL:
Java:
Javaのレコード型はバージョン14で実験的に導入された機能であり、バージョン16で正式な仕様となった。ただしJavaのレコードは、内部的にはクラスで実現される糖衣構文である。レコードの専用構文がない言語であっても、クラス構文をサポートする場合は、ほとんどの場面においてクラスで代用することが可能である。