Records
Records allow us to refer to the fields by name and not position. We use a record instead of a tuple to store the data.
If we write a record definition of the type shown below, we can then refer to the fields of the record by name.
-record(person, {name, phone, address}).
For example, if P is now a variable whose value is a person record, we can code as follows in order to access the name
and address fields of the records.
Name = P#person.name,
Address = P#person.address,
...
Internally, records are represented using tagged tuples:
{person, Name, Phone, Address}
Defining a Record
This definition of a person will be used in many of the examples which follow. It contains three fields, name, phone and
address. The default values for name and phone is "" and [], respectively. The default value for address is the atom undefined,
since no default value is supplied for this field:
-record(person, {name = "", phone = [], address}).
We have to define the record in the shell in order to be able use the record syntax in the examples:
> rd(person, {name = "", phone = [], address}).
person
This is due to the fact that record definitions are available at compile time only, not at runtime.
Creating a Record
A new person record is created as follows:
> #person{phone=[0,8,2,3,4,3,1,2], name="Robert"}.
#person{name = "Robert",phone = [0,8,2,3,4,3,1,2],address = undefined}
Since the address field was omitted, its default value is used.
There is a new feature introduced in Erlang 5.1/OTP R8B, with which you can set a value to all fields in a record, overriding
the defaults in the record specification. The special field _, means "all fields not explicitly specified".
> #person{name = "Jakob", _ = '_'}.
#person{name = "Jakob",phone = '_',address = '_'}
It is primarily intended to be used in ets:match/2 and mnesia:match_object/3, to set record fields to the atom '_'. (This is
a wildcard in ets:match/2.)
Accessing a Record Field
> P = #person{name = "Joe", phone = [0,8,2,3,4,3,1,2]}.
#person{name = "Joe",phone = [0,8,2,3,4,3,1,2],address = undefined}
> P#person.name.
"Joe"
Updating a Record
> P1 = #person{name="Joe", phone=[1,2,3], address="A street"}.
#person{name = "Joe",phone = [1,2,3], address = "A street"}
> P2 = P1#person{name="Robert"}.
#person{name = "Robert",phone = [1,2,3],address = "A street"}
Type Testing
The following example shows that the guard succeeds if P is record of type person.
foo(P) when is_record(P, person) -> a_person;
foo(_) -> not_a_person.
Pattern Matching
Matching can be used in combination with records as shown in the following example:
> P3 = #person{name="Joe", phone=[0,0,7], address="A street"}.
#person{name = "Joe",phone = [0,0,7],address = "A street"}
> #person{name = Name} = P3, Name.
"Joe"
The following function takes a list of person records and searches for the phone number of a person with a particular name:
find_phone([#person{name=Name, phone=Phone} | _], Name) ->
{found, Phone};
find_phone([_| T], Name) ->
find_phone(T, Name);
find_phone([], Name) ->
not_found.
The fields referred to in the pattern can be given in any order.
Nested Records
The value of a field in a record might be an instance of a record. Retrieval of nested data can be done stepwise, or in a single step,
as shown in the following example:
-record(name, {first = "Robert", last = "Ericsson"}).
-record(person, {name = #name{}, phone}).
demo() ->
P = #person{name= #name{first="Robert",last="Virding"}, phone=123},
First = (P#person.name)#name.first.
In this example, demo() evaluates to "Robert".
April 1st Wednesday (四月 一日 水曜日)
最新推荐文章于 2023-08-15 15:56:49 发布