April 1st Wednesday (四月 一日 水曜日)

来源:互联网 发布:黑莓9810软件下载 编辑:程序博客网 时间:2024/05/07 17:05

 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".

原创粉丝点击