在Erlang内部只有两种混合的数据类型:List和Tuple,而这两种都不支持命名访问,所以如果没有额外的库的话想创建像PHP、Ruby或Python中的关联数组(Ruby中的Hash)是不可能的
在Ruby中我可以这样做:
复制代码 代码如下:
server_opts = {:port => 8080, :ip => '127.0.0.1', :max_connections => 10}
在Erlang的语法级别不支持这种表达
为了避免这种限制,Erlang虚拟机提供了一个伪数据类型,称为Record
Record支持命名访问,后面我们会看到为什么我们称之为“伪”数据类型
定义Record
Record更类似于C中的struct,而不是关联数组,后者必须一开始就定义好内容并且只能保持数据
这里是一个服务器的连接选项的Record例子:
复制代码 代码如下:
-module(my_server).
-record(server_opts,
{port,
ip="127.0.0.1",
max_connections=10}).
% The rest of your code goes here.
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的实例的合法方式:
复制代码 代码如下:
Opts1 = #server_opts{port=80}.
这段代码创建了一个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,我可以这样做:
复制代码 代码如下:
Opts = #server_opts{port=80, ip="192.168.0.1"},
Opts#server_opts.port
每次你想访问一个Record时你都必须包含Record的名字,为什么要这样?
因为Record不是真正的内部数据类型,它只是编译器的小把戏。
在内部,Record是Tuple,如下:
复制代码 代码如下:
{server_opts, 80, "127.0.0.1", 10}
编译器将Record的名字映射到Tuple里面
Erlang虚拟机记录了Record的定义,而编译器将所有的Record逻辑翻译为Tuple逻辑
因此,根本就没有Record类型,所以每次你访问一个Record时你必须告诉Erlang我们在用哪个Record(为了编译器爽,程序员变的很不爽)
更新Record
更新Record和创建Record很类似:
复制代码 代码如下:
Opts = #server_opts{port=80, ip="192.168.0.1"},
NewOpts = Opts#server_opts{port=7000}.
这里首先创建一个server_opts Record
NewOpts = Opts#{port=7000}创建了一个Opts的副本,并指定port为7000并绑定到NewOpts
匹配Record和Guard语句
不谈模式匹配就不算Erlang
让我们来看看一个例子:
复制代码 代码如下:
handle(Opts=#server_opts{port=8000}) ->
% do special port 8080 stuff
handle(Opts=#server_opts{} ->
% default stuff
Guard语句和上面的类似,例如绑定小于1024的端口通常需要root权限,所以我们可以这样做:
复制代码 代码如下:
handle(Opts) when Opts#server_opts.port <= 1024 ->
% requires root access
handle(Opts=#server_opts{}) ->
% Doesn't require root access
使用Record
在我使用Erlang的有限的时间里,我发现Record主要用在两种场景
首先,Record用来保存状态,特别是在使用gen_server的behaviour时
由于Erlang不能全局保持状态,所以状态必须在方法之前传来传去
然后,Record可以用来保存配置选项,这可以认为是第一点的子集
尽管如此,Record也有一些限制,最明显的是不能在运行时添加和删除field,这和C的struct一样,Record的结构必须预先定义
如果你想在运行时添加和删除field,或者你在运行时才能确定有哪些field,这时你应该使用dict而不是Record
Erlang,Record
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。