非常教程

Erlang 20参考手册

指南:参考手册 | Guide: Reference manual

10.记录 | 10. Records

记录是用于存储固定数量的元素的数据结构。它命名了字段并且与C中的结构类似。在编译期间,记录表达式被转换为元组表达式。因此,除非采取特殊行动,否则shell不能理解记录表达式。有关详细信息,请参阅shell(3)STDLIB中的手册页。

提供了更多示例Programming Examples

10.1定义记录

记录定义包括记录的名称,后跟记录的字段名称。记录和字段名称必须是原子。每个字段可以被赋予一个可选的默认值。如果没有提供默认值,undefined则使用。

-record(Name, {Field1 [= Value1],
               ...
               FieldN [= ValueN]}).

记录定义可以放置在模块的属性和函数声明中的任意位置,但定义必须在记录的任何用法之前出现。

如果在多个模块中使用了记录,则建议将记录定义放在包含文件中。

10.2创造记录

以下表达式创建一个新Name记录,其中每个字段FieldI的值是评估相应表达式的值ExprI

#Name{Field1=Expr1,...,FieldK=ExprK}

这些字段可以以任何顺序排列,不一定与记录定义中的顺序相同,并且字段可以省略。省略字段取代它们各自的默认值。

如果要为多个字段分配相同的值,则可以使用以下构造:

#Name{Field1=Expr1,...,FieldK=ExprK, _=ExprL}

省略字段然后获得评估值ExprL而不是默认值。此功能主要用于为ETS和Mnesia匹配功能创建模式。

例子:

-record(person, {name, phone, address}).

...

lookup(Name, Tab) ->
    ets:match_object(Tab, #person{name=Name, _='_'}).

10.3访问记录字段

Expr#Name.Field

返回指定字段的值。Expr是评估一个Name记录。

以下表达式返回指定字段在记录元组表示中的位置:

#Name.Field

例子:

-record(person, {name, phone, address}).

...

lookup(Name, List) ->
    lists:keysearch(Name, #person.name, List).

10.4更新记录

Expr#Name{Field1=Expr1,...,FieldK=ExprK}

Expr是评估一个Name记录。将返回此记录的副本,每个指定字段FieldI的值更改为评估相应表达式的值ExprI。所有其他领域保留其旧值。

10.5守卫记录

由于记录表达式扩展为元组表达式,因此在守卫中允许创建记录和访问记录字段。但是,例如,对于字段启动,所有的子表达式也必须是有效的警戒表达式。

例子:

handle(Msg, State) when Msg==#msg{to=void, no=3} ->
    ...

handle(Msg, State) when State#state.running==true ->
    ...

还有一个类型测试BIF is_record(Term, RecordTag)

例子:

is_person(P) when is_record(P, person) ->
    true;
is_person(_P) ->
    false.

10.6记录模式

与创建记录相同的方式创建匹配某个记录的模式:

#Name{Field1=Expr1,...,FieldK=ExprK}

在这种情况下,一个或多个Expr1... ExprK可以是未绑定的变量。

10.7嵌套记录

从Erlang/OTP R14开始,在访问或更新嵌套记录时可以省略括号。假定以下记录定义:

-record(nrec0, {name = "nested0"}).
-record(nrec1, {name = "nested1", nrec0=#nrec0{}}).
-record(nrec2, {name = "nested2", nrec1=#nrec1{}}).

N2 = #nrec2{},
    

在R14之前,需要括号如下:

"nested0" = ((N2#nrec2.nrec1)#nrec1.nrec0)#nrec0.name,
N0n = ((N2#nrec2.nrec1)#nrec1.nrec0)#nrec0{name = "nested0a"},
    

自R14以来,还可以写以下内容:

"nested0" = N2#nrec2.nrec1#nrec1.nrec0#nrec0.name,
N0n = N2#nrec2.nrec1#nrec1.nrec0#nrec0{name = "nested0a"},

10.8记录的内部表述

在编译期间,记录表达式被翻译成元组表达式。定义为:

-record(Name, {Field1,...,FieldN}).

在内部由元组表示:

{Name,Value1,...,ValueN}

这里每个ValueI都是默认值FieldI

对于每个使用记录的模块,编译期间会添加一个伪函数以获取有关记录的信息:

record_info(fields, Record) -> [Field]
record_info(size, Record) -> Size

Size 是元组表示的大小,即比字段数多一个。

另外,#Record.Name返回Name记录的元组表示中的索引Record

Name 必须是一个原子。

Erlang 20

Erlang 是一种通用的面向并发的编程语言,可应付大规模开发活动的程序设计语言和运行环境。

主页 https://www.erlang.org/
源码 https://github.com/erlang/otp
版本 20
发布版本 20.1