レコードは特殊なタプルです。 普通のタプルの中にある要素は位置で特定するのに対し、レコードは要素を名前で特定します。
要素を位置で特定するということは、どの場所にどの要素があるということを覚えていなくてはなりません。
例えば、
{Name, Address, Phone}
というタプルがあるとすると、名前は一つ目の要素、住所は二つ目の要素、電話番号は三つ目の要素、と覚えておかなければなりません。
もし順番を取り間違えたら、プログラムは予期していない実行結果を出すかもしれません。
これに対して、先ほど説明した通りレコードは要素を名前で特定することが可能です。 これはCの構造体に非常に良く似ています。
Cの構造体で商品という型を作成します。これは商品の要素にID、名前、価格があると宣言されているだけです。
struct item{
int id;
char[20] name;
int price;
}
Erlangのレコードを使って同じものを表してみます。-record()の中身に注目して下さい。
-record(item, {id,name,price}).
これはitemという型を作ったというようなニュアンスを持っています。 そして、その型の中身はid,name,priceなのですね。
ちなみに、上の形はモジュールやファイル内での宣言の形となっています。 シェルに打ち込んでもエラーが表示されてしまいます。
レコードを利用するためには決まったやり方があります。
まず始めにシェル内でレコードを作成して実験してみます。
関数rd()を使うことによってレコードを作成することが可能です。
1> rd(item, {id,name,price}).
item
一番最初の例とよく似ていますね。先ほどはモジュール内の宣言で、今回は関数を使っています。
レコードを利用してみます。
2> #item{}.
#item{id = undefined,name = undefined,price = undefined}
これはレコードの定義を確認しています。要素はundefinedとなっていて、指定されていないことが示されていますね。
実際にレコードの型に値を代入してみます。
Apple = #item{id=431,name=apple,price=200}.
#item{id = 431,name = apple,price = 200}
4> Apple.
#item{id = 431,name = apple,price = 200}
変数Appleが作成されていますね。
要素は全て設定する必要はありません。
5> Orange = #item{name=orange}.
#item{id = undefined,name = orange,price = undefined}
設定されていない場所はundefinedという値になっています。undefinedはデフォルト値です。
また、要素の値も取り出すことが可能です。
6> #item{name= Name,price= Price} = Apple.
#item{id = 431,name = apple,price = 200}
8> Name.
apple
9> Price.
200
10>
最後に、レコードの一部だけ変える例をやります。
Apple2 = Apple#item{price = 150}.
#item{id = 431,name = apple,price = 150}
指定された要素だけ上書きされていますね。
先ほどのレコードは関数で作成しましたが、宣言で作成するほうが一般的です。
今回はファイルのインクルードによる手法を使います。
ファイルのインクルードとは、ファイルの中に書いてあるものを取り込むことです。
以下のファイルを用意して下さい。
ファイル名
myrecords.hrl
-record(item, {
id = 0000,
name = item_name
value
}).
上のファイルを読み込みます。
2> rr("myrecords.hrl").
[item]
rr()という関数は read record (レコードを読む)する関数です。
item というレコードを読み取っていますね。
レコードの書式は以下のようになっています。
-record(RecordName,{
key1 = value1,
key2 = value2,
key3,
key4
}).
key1とkey2にはデフォルト値が設定してあります。
key3とkey4はデフォルト値がないので、 key3 = undefined というように初期化されています。
上で作成したレコードがどうなっているか確認してみましょう。
3> #item{}.
#item{id = 0,name = item_name,value = undefined}
確かにデフォルト値が変化していますね。
レコードを普通のタプルに戻すことも可能です。
忘れさせたいレコードに対して、rf()関数を利用して下さい。
> rf(item).
ok
> Apple.
{item,431,apple,150}
レコードの要素「 _ 」は指定されていない要素全てという意味を持ちます。
> #item{name=apple, _ = '_'}.
#item{id = '_',name = apple,price = '_'}
レコードの要素一つだけを抽出する。
> Apple = #item{id=431,name=apple,price=200}.
#item{id = 431,name = apple,price = 200}
> Name = Apple#item.name.
apple
任意のレコードの判定
> Apple = #item{id=431,name=apple,price=200}.
#item{id = 431,name = apple,price = 200}
> is_record(Apple, item).
true
> Orang = {333,orange,100}.
{333,orange,100}
> is_record(Orange, item).
false