zoukankan      html  css  js  c++  java
  • 说说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


  • 相关阅读:
    正则表达式
    什么是面向对象
    关于jdk,jre,jvm和eclipse的一些总结
    分析ajax爬取今日头条街拍美图
    pycharm误删恢复方法及python扩展包下载地址
    django 之 视图层、模板层
    django
    django框架基础二
    jdango框架基础一
    安装软件,提高速度,可以使用清华源
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7403414.html
Copyright © 2011-2022 走看看