说说erlang tuple和record结构
erlang有两种复合结构。tuple和list,两者的区别是tuple子元素的个数是固定不变的。声明后就不能改变了。而list是可变的,能够通过[H|T]来取出或插入新元素。
record有点像C/C++里面的结构体。实际上是语法糖,方便我们的开发。代码汇编时转成tuple表达形式。
Tuple
tuple的表示方法如:
{Term1,...,TermN}
以下以样例说明erlang tuple及一些基本操作:
1> A = {1,2}.
{1,2}
2> tuple_size(A).
2
3> is_tuple(A).
true
4> tuple_to_list(A).
[1,2]
5> element(1, A).
1
6> setelement(2, A, 3).
{1,3}
Record
record有点像C/C++里面的结构体。表示方法如:
-record(Name, {Field1 [= Value1],
...
FieldN [= ValueN]}).
以下以样例说明erlang record及一些基本操作:
%% shell下定义 record结构 person
%% 等效程序里定义 -record(person, {name, age}).
7> rd(person, {name, age}).
person
8> A1 = #person{name = "john", age = 10}.
#person{name = "john",age = 10}
9> A2 = A1#person{name = "Lucy"}.
#person{name = "Lucy",age = 10} %% record 一次赋值
10> X = #person{_ = 1}.
#person{name = 1,age = 1}
11> element(2, X).
1
12> setelement(2, X, "Tom").
#person{name = "Tom",age = 1}
14> P=#person{}.
#person{name = undefined,age = undefined}
15> is_record(P,person).
true
16> #person.age.
3
17> #person.name.
2
tuple 和 record 有什么关系?
record仅仅是语言程序上的结构,方便我们的开发,在erlang编译的时候会转成tuple处理
%% shell下定义 record结构 person2
%% 等效程序里定义 -record(person2, {name = "", age = 1}).
23> rd(person2, {name = "", age = 1}).
person2
24> A3 = #person2{name = "Jimmy"}.
#person2{name = "Jimmy",age = 1} %% 模式匹配
25> {_, Name, _} = A3.
#person2{name = "Jimmy",age = 0}
26> Name.
"Jimmy"
27> #person2{name = Name2} = A3.
#person2{name = "Jimmy",age = 0}
28> Name2.
"Jimmy"
以下,以一个简单的样例,測试tuple和record的汇编代码
-module(test). -export([test/0]). -record(person, {name, age}). test() ->
A = {person, "Tom", 1},
B = #person{name = "Tom", age = 1},
{A,B}.
通过命令erlc -S test.erl 能够生成 test.S的汇编代码
{function, test, 0, 2}.
{label,1}.
{line,[{location,"c:/test.erl",7}]}.
{func_info,{atom,test},{atom,test},0}.
{label,2}.
{move, {literal, { {person,"Tom",1} ,{person,"Tom",1}} }, {x,0} }.
return.
record_info/2
说到record,不得不提record_info/2,这个函数用以获取record的信息,原型:
record_info(Type, Record) -> integer() | list
Type有两种:size、fields
34> rd(person,{id, name}).
person
35> record_info(fields, person).
[id,name]
36> record_info(size, person).
3
record_info/2实际上一个语法糖。写个样例tt.erl说明一下:
-module(tt).
-compile(export_all). -record(person,{id, name, age}).
fields() ->
record_info(fields, person). size() ->
record_info(size, person).
erlc -S tt.erl
编译这个模块得到 tt.S,这是当中的汇编码:
{function, fields, 0, 2}.
{label,1}.
{line,[{location,"tt.erl",5}]}.
{func_info,{atom,tt},{atom,fields},0}.
{label,2}.
{move,{literal, [id,name,age] },{x,0}}.
return.
{function, size, 0, 4}.
{label,3}.
{line,[{location,"tt.erl",8}]}.
{func_info,{atom,tt},{atom,size},0}.
{label,4}.
{move, {integer,4} ,{x,0}}.
return.
在编译期就直接被erlang优化了
改动tuple结构
R16以后。erlang提供了2个接口用于改动tuple结构。
1、添加tuple元素
erlang:append_element(Tuple1, Term)
> erlang:append_element({one, two}, three).
{one,two,three}
等效于 list_to_tuple(tuple_to_list(Tuple1) ++ [Term]),但性能比后者高
2、移除tuple元素
erlang:delete_element(Index, Tuple1)
> erlang:delete_element(2, {one, two, three}).
{one,three}
record 的模式匹配
record有两种模式匹配的方法:
1> rd(person, {a,b}).
person
2> case #person{a=10} of #person{a=A} -> A; _ -> false end.
10
3> A.
10
4> #person{a=B} = #person{a=15}.
#person{a = 15,b = undefined}
5> B.
15
如今,顺道讨论下 record 模式匹配的本质。
1> rd(person, {a,b}).
person
2> #person{} =:= #person{a=1}.
false
3> case #person{a=1} of #person{} -> true; _ -> false end.
true
4> #person{} = #person{a=1}.
#person{a = 1,b = undefined}
前面说到 record在执行期会编译成tuple,所以第2点是推断两个tuple是否同样。
而第3点和第4点本质区别不大,仅仅是执行了模式匹配,检查tuple是否 3 个元素。且第一个元素是原子person,不会推断除其它元素值是否相等。可是假设像以下这样写就会匹配到其它元素了。
5> case #person{a=1} of #person{a=3} -> true; _ -> false end.
false
6> #person{a=3} = #person{a=1}.
** exception error: no match of right hand side value #person{a = 1,b = undefined}
有兴趣的同学參照上面打印erlang模块汇编码就能够找到答案了。
更新说明:
2014/10/30 补充了record函数 record_info/2的说明
2014/11/06 补充了record函数is_record/2等基本操作
2015/2/11 补充了两个tuple结构改动函数
2015/3/4 补充了record的模式匹配
參考:http://blog.csdn.net/mycwq/article/details/31421341
说说erlang tuple和record结构的更多相关文章
- Erlang中的record与宏
http://www.cnblogs.com/me-sa/archive/2011/07/20/erlang0006.html 在Erlang中使用Tuple ,数据项的顺序\数量都是确定的,一旦数据 ...
- Erlang--etc结构解析
Erlang中可以用List表达集合数据,但是如果数据量特别大的话在List中访问元素就会变慢了;这种主要是由于List的绝大部分操作都是基于遍历完成的. Erlang的设计目标是软实时(参考:htt ...
- Erlang ETS Table
不需要显示用锁,插入和查询时间不仅快而且控制为常量,这就是Erlang的ETS Table. 为什么而设计? Erlang中可以用List表达集合数据,但是如果数据量特别大的话在List中访问元素就会 ...
- [Erlang 0117] 当我们谈论Erlang Maps时,我们谈论什么 Part 2
声明:本文讨论的Erlang Maps是基于17.0-rc2,时间2014-3-4.后续Maps可能会出现语法或函数API上的有所调整,特此说明. 前情提要: [Erlang 0116] 当我们谈论E ...
- [Erlang 0116] 当我们谈论Erlang Maps时,我们谈论什么 Part 1
Erlang 增加 Maps数据类型并不是很突然,因为这个提议已经进行了2~3年之久,只不过Joe Armstrong老爷子最近一篇文章Big changes to Erlang掀起不小了风 ...
- 当我们谈论Erlang Maps时,我们谈论什么 Part 2
声明:本文讨论的Erlang Maps是基于17.0-rc2,时间2014-3-4.兴许Maps可能会出现语法或函数API上的有所调整,特此说明. 前情提要: [Erlang 0116] 当我们谈论E ...
- 当我们谈论Erlang Maps时,我们谈论什么 Part 1
Erlang 添加 Maps数据类型并非非常突然,由于这个提议已经进行了2~3年之久,仅仅只是Joe Armstrong老爷子近期一篇文章Big changes to Erlang掀起不小了 ...
- Erlang 初学者技巧及避免的陷阱
1. 传参或在匿名函数内慎用self() 通常在做消息传递或新建进程的时候我们需要将当前进程的Pid发给目标进程以便接收返回信息,但初学者不留意容易犯以下错误 spawn(fun() -> lo ...
- Erlang 进程被抢占的条件——一个进程长时霸占调度器的极端示例
最近研究 binary 的实现和各种操作对应的 beam 虚拟机汇编指令,发现有一些指令序列是不可重入的,比如说有的指令构造一个上下文(也就是某种全局状态),然后下一条指令会对这个上下文做操作(具体的 ...
随机推荐
- zabbix安装和配置
- C#为什么要多线程开发(一)
首先说下多线程出现的原因: 为了解决负载均衡问题,充分利用CPU资源.为了提高CPU的使用率,采用多线程的方式去同时完成几件事情而不互相干扰.为了处理大量的IO操作时或处理的情况需要花费大量的时间等等 ...
- 7种方法实现移动端Retina屏幕1px边框效果
在Reina(视网膜)屏幕的手机上,使用CSS设置的1px的边框实际会比视觉稿粗很多.在之前的项目中,UI告诉我说我们移动项目中的边框全部都变粗了,UI把他的设计稿跟我的屏幕截图跟我看,居然真的不一样 ...
- ARC101E - Ribbons on Tree
题目链接 ARC101E - Ribbons on Tree 题解 令边集\(S \subseteq E\) 设\(f(S)\)为边集S中没有边被染色的方案数 容斥一下,那么\(ans = \sum_ ...
- tomcat环境变量详细配置步骤
这篇文章主要为大家详细介绍了tomcat环境变量配置步骤,包括JDK环境变量配置,感兴趣的小伙伴们可以参考一下 本文实例为大家分享了tomcat环境变量的配置教程,供大家参考,具体内容如下 1.=== ...
- mac中安装 RabbitMQ
1.brew install rabbitmq 2.安装后,进入/usr/local/Cellar/rabbitmq/3.7.7 ,输入:sbin/rabbitmq-server 出现下面日志,说明启 ...
- IDEA的安装
https://blog.csdn.net/when_to_return/article/details/81590356
- bzoj 1008
记得取模时对答案的处理 #include<bits/stdc++.h> #define ll long long using namespace std; ; ll qpow(ll a,l ...
- Python基础-字符串、集合类型、判断、深拷贝与浅拷贝、文件读写
字符串 1.定义三个变量: 2.交换两个变量值 1)引入第三个变量: 2)Python引入第三方变量: 3)不引入第三方变量: 3. isalpha 是否是汉字或字母 4.Isalnum 是否是汉字 ...
- MySQL创建用户的三种方法 (并授权)转
前言:MySQL创建用户的方法分成三种:INSERT USER表的方法.CREATE USER的方法.GRANT的方法. 一.账号名称的构成方式 账号的组成方式:用户名+主机(所以可以出现重复的用户名 ...