欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Erlang中的Record详解

程序员文章站 2022-06-17 08:13:47
在erlang内部只有两种混合的数据类型:list和tuple,而这两种都不支持命名访问,所以如果没有额外的库的话想创建像php、ruby或python中的关联数组(rub...

在erlang内部只有两种混合的数据类型:list和tuple,而这两种都不支持命名访问,所以如果没有额外的库的话想创建像php、ruby或python中的关联数组(ruby中的hash)是不可能的

在ruby中我可以这样做:

在erlang的语法级别不支持这种表达

为了避免这种限制,erlang虚拟机提供了一个伪数据类型,称为record
record支持命名访问,后面我们会看到为什么我们称之为“伪”数据类型

定义record

record更类似于c中的struct,而不是关联数组,后者必须一开始就定义好内容并且只能保持数据
这里是一个服务器的连接选项的record例子:

record使用-record指令来声明,第一个参数是record的名字,第二个参数是一个tuple,tuple包含了record里的field和默认值
在这里我们定义了server_opts这个record,它有三个field:端口、ip和最大连接数
没有默认的port,ip默认值为"127.0.0.1",max_connections默认值为10

创建record

record通过使用#符号来创建,下面是创建server_opts这个record的实例的合法方式:

这段代码创建了一个server_opts record,port设置为80,其他field使用默认值
opts2 = #server_opts{port=80, ip="192.168.0.1"}. 

这段代码创建了一个server_opts record,但是ip设置为"192.168.0.1"

简而言之,当创建一个record时,你可以包含任何field,省略的field将使用默认值

访问record

record的访问方式很笨拙,如果我想访问port这个field,我可以这样做:

每次你想访问一个record时你都必须包含record的名字,为什么要这样?
因为record不是真正的内部数据类型,它只是编译器的小把戏。

在内部,record是tuple,如下:

编译器将record的名字映射到tuple里面
erlang虚拟机记录了record的定义,而编译器将所有的record逻辑翻译为tuple逻辑
因此,根本就没有record类型,所以每次你访问一个record时你必须告诉erlang我们在用哪个record(为了编译器爽,程序员变的很不爽)

更新record

更新record和创建record很类似:

这里首先创建一个server_opts record

newopts = opts#{port=7000}创建了一个opts的副本,并指定port为7000并绑定到newopts

匹配record和guard语句

不谈模式匹配就不算erlang
让我们来看看一个例子:

guard语句和上面的类似,例如绑定小于1024的端口通常需要root权限,所以我们可以这样做:

使用record

在我使用erlang的有限的时间里,我发现record主要用在两种场景
首先,record用来保存状态,特别是在使用gen_server的behaviour时
由于erlang不能全局保持状态,所以状态必须在方法之前传来传去
然后,record可以用来保存配置选项,这可以认为是第一点的子集
尽管如此,record也有一些限制,最明显的是不能在运行时添加和删除field,这和c的struct一样,record的结构必须预先定义
如果你想在运行时添加和删除field,或者你在运行时才能确定有哪些field,这时你应该使用而不是record

相关标签: Erlang Record