1.记录 | 1. Records
1 记录
1.1纪录及元组
使用记录而不是元组的主要优点是记录中的字段是按名称访问的,而元组中的字段是按位置访问的。为了说明这些差异,假设你想用元组表示一个人{Name, Address, Phone}
。
若要编写操作此数据的函数,请记住以下内容:
Name
字段是元组的第一个元素。
Address
领域是第二个元素。
Phone
领域是第三个要素。
例如,要从P
包含这样的元组的变量中提取数据,可以编写以下代码,然后使用模式匹配来提取相关字段:
Name = element(1, P),
Address = element(2, P),
...
这样的代码很难阅读和理解,如果元组中元素的编号是错误的,就会发生错误。如果字段的数据表示发生了变化,则通过重新排序,添加或删除字段,必须检查并修改所有对人员元组的引用。
记录允许按名称引用字段,而不是按位置引用。在以下示例中,将使用记录而不是元组来存储数据:
-record(person, {name, phone, address}).
这使得能够通过名称引用记录的字段。例如,如果P
是值为person
记录的变量,则以下代码将访问记录的名称和地址字段:
Name = P#person.name,
Address = P#person.address,
...
在内部,记录使用标记元组来表示:
{person, Name, Phone, Address}
1.2定义记录
person
本节中的几个示例中使用了以下a的定义。三个字段包括,name
,phone
,和address
。name
and 的默认值分别为phone
“”和[]。默认值address
是原子undefined
,因为没有为该字段提供默认值:
-record(person, {name = "", phone = [], address}).
必须在shell中定义记录,以便在示例中使用记录语法:
> rd(person, {name = "", phone = [], address}).
person
这是因为记录定义只能在编译时才能使用,而不能在运行时使用。有关shell中记录的详细信息,请参阅shell(3)
STDLIB中的手册页。
1.3创造记录
新的person
记录创建如下:
> #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}
就像address
字段,则使用其默认值。
从Erlang 5.1 / OTP R8B开始,可以使用特殊字段设置记录中所有字段的值_
。_
指“未明确指定的所有字段”。
例子:
> #person{name = "Jakob", _ = '_'}.
#person{name = "Jakob",phone = '_',address = '_'}
它主要用于ets:match/2
和mnesia:match_object/3
为记录字段设置原子'_'
。(这是一个通配符ets:match/2
。)
1.4访问记录字段
以下示例显示如何访问记录字段:
> 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"
1.5更新记录
下面的示例演示如何更新记录:
> 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"}
1.6型试验
以下示例显示如果P
是记录类型,则防护成功person
:
foo(P) when is_record(P, person) -> a_person;
foo(_) -> not_a_person.
1.7模式匹配
匹配可以与记录结合使用,如以下示例所示:
> 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"
以下功能获取person
记录列表并搜索具有特定姓名的人的电话号码:
find_phone([#person{name=Name, phone=Phone} | _], Name) ->
{found, Phone};
find_phone([_| T], Name) ->
find_phone(T, Name
find_phone([], Name) ->
not_found.
模式中引用的字段可以按任何顺序给出。
1.8嵌套记录
记录中字段的值可以是记录的实例。可以逐步完成嵌套数据的检索,也可以在一个步骤中完成,如以下示例所示:
-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.
在这里,demo()
评估"Robert"
。
1.9更长的例子
以下示例中嵌入了注释:
%% File: person.hrl
%%-----------------------------------------------------------
%% Data Type: person
%% where:
%% name: A string (default is undefined).
%% age: An integer (default is undefined).
%% phone: A list of integers (default is []).
%% dict: A dictionary containing various information
%% about the person.
%% A {Key, Value} list (default is the empty list).
%%------------------------------------------------------------
-record(person, {name, age, phone = [], dict = []}).
-module(person).
-include("person.hrl").
-compile(export_all). % For test purposes only.
%% This creates an instance of a person.
%% Note: The phone number is not supplied so the
%% default value [] will be used.
make_hacker_without_phone(Name, Age) ->
#person{name = Name, age = Age,
dict = [{computer_knowledge, excellent},
{drinks, coke}]}.
%% This demonstrates matching in arguments
print(#person{name = Name, age = Age,
phone = Phone, dict = Dict}) ->
io:format("Name: ~s, Age: ~w, Phone: ~w ~n"
"Dictionary: ~w.~n", [Name, Age, Phone, Dict]).
%% Demonstrates type testing, selector, updating.
birthday(P) when record(P, person) ->
P#person{age = P#person.age + 1}.
register_two_hackers() ->
Hacker1 = make_hacker_without_phone("Joe", 29),
OldHacker = birthday(Hacker1),
% The central_register_server should have
% an interface function for this.
central_register_server ! {register_person, Hacker1},
central_register_server ! {register_person,
OldHacker#person{name = "Robert",
phone = [0,8,3,2,4,5,3,1]}}.