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结构的更多相关文章

  1. Erlang中的record与宏

    http://www.cnblogs.com/me-sa/archive/2011/07/20/erlang0006.html 在Erlang中使用Tuple ,数据项的顺序\数量都是确定的,一旦数据 ...

  2. Erlang--etc结构解析

    Erlang中可以用List表达集合数据,但是如果数据量特别大的话在List中访问元素就会变慢了;这种主要是由于List的绝大部分操作都是基于遍历完成的. Erlang的设计目标是软实时(参考:htt ...

  3. Erlang ETS Table

    不需要显示用锁,插入和查询时间不仅快而且控制为常量,这就是Erlang的ETS Table. 为什么而设计? Erlang中可以用List表达集合数据,但是如果数据量特别大的话在List中访问元素就会 ...

  4. [Erlang 0117] 当我们谈论Erlang Maps时,我们谈论什么 Part 2

    声明:本文讨论的Erlang Maps是基于17.0-rc2,时间2014-3-4.后续Maps可能会出现语法或函数API上的有所调整,特此说明. 前情提要: [Erlang 0116] 当我们谈论E ...

  5. [Erlang 0116] 当我们谈论Erlang Maps时,我们谈论什么 Part 1

         Erlang 增加 Maps数据类型并不是很突然,因为这个提议已经进行了2~3年之久,只不过Joe Armstrong老爷子最近一篇文章Big changes to Erlang掀起不小了风 ...

  6. 当我们谈论Erlang Maps时,我们谈论什么 Part 2

    声明:本文讨论的Erlang Maps是基于17.0-rc2,时间2014-3-4.兴许Maps可能会出现语法或函数API上的有所调整,特此说明. 前情提要: [Erlang 0116] 当我们谈论E ...

  7. 当我们谈论Erlang Maps时,我们谈论什么 Part 1

         Erlang 添加 Maps数据类型并非非常突然,由于这个提议已经进行了2~3年之久,仅仅只是Joe Armstrong老爷子近期一篇文章Big changes to Erlang掀起不小了 ...

  8. Erlang 初学者技巧及避免的陷阱

    1. 传参或在匿名函数内慎用self() 通常在做消息传递或新建进程的时候我们需要将当前进程的Pid发给目标进程以便接收返回信息,但初学者不留意容易犯以下错误 spawn(fun() -> lo ...

  9. Erlang 进程被抢占的条件——一个进程长时霸占调度器的极端示例

    最近研究 binary 的实现和各种操作对应的 beam 虚拟机汇编指令,发现有一些指令序列是不可重入的,比如说有的指令构造一个上下文(也就是某种全局状态),然后下一条指令会对这个上下文做操作(具体的 ...

随机推荐

  1. Xamarin Essentials教程磁力计Magnetometer

    Xamarin Essentials教程磁力计Magnetometer   磁力计也叫地磁.磁感器,可用于测试磁场强度和方向.在手持设备中,通过磁力计可以计算设备的左右.前后倾斜角度,广泛应用于手机各 ...

  2. 改变字体大小实现自适应之js方案A

    一.元素大小有两种写法 1.写结果:设计师给的移动端页面sketch设计稿一般是750px宽度,在sublime编辑器里,设置cssrem或rem-unit插件为56px的字体大小.做页面时,设计稿是 ...

  3. chrome插件的开发

    基本目录:icon,manifest,html,js. chrome插件的使用,运行,打包. chrome浏览器打开扩展,勾选开发者模式,点击加载没打包的扩展,选中目录,加载插件. 右上角出现插件图标 ...

  4. Python基础知识—sys模块初探

    有关Python解释器的信息 与所有其他模块一样,必须使用import语句导入sys模块,即import sys. sys模块提供有关Python解释器的常量,函数和方法.dir(系统)给出了可用常量 ...

  5. mongodb更新数组元素中的字段,数组$占位符

    pppCodes为数组,PPPCode,expiredOn为数组元素中的字段 db.getCollection('users').findOneAndUpdate({ _id: userId, 'pp ...

  6. IntelliJ IDEA classpath包含哪些文件夹以及如何把文件(夹)添加到classpath下

    在IDEA中,标为蓝色的文件夹被认定为包含在classpath中,例如上图中的resources.src文件夹.把文件位置以"classpath:applicationContext.xml ...

  7. Module not found: Error: Can't resolve 'XXX' in 'XXXX'

    故障 控制台运行webpack/npm时出现 Module not found: Error: Can't resolve 'XXX' in 'XXXX' 解决方案 npm i XXX --save ...

  8. HDU 2002 计算球体积

    题目链接:HDU 2002 Description 根据输入的半径值,计算球的体积. Input 输入数据有多组,每组占一行,每行包括一个实数,表示球的半径. Output 输出对应的球的体积,对于每 ...

  9. mysql:Cannot proceed because system tables used by Event Scheduler were found damaged at server start

    mysql 5.7.18 sqlyog访问数据库,查看表数据时,出现 Cannot proceed because system tables used by Event Scheduler were ...

  10. 常见的git清单

    我们每天使用 Git ,但是很多命令记不住. 一般来说,日常使用只要记住下图6个命令,就可以了.但是熟练使用,恐怕要记住60-100个命令. 这篇文章是从别人博客上copy重新整理出来的,作为笔记用, ...