說說erlang tuple和record結構

erlang有兩種複合結構。tuple和list,二者的區別是tuple子元素的個數是固定不變的。聲明後就不能改變了。而list是可變的,可以經過[H|T]來取出或插入新元素。shell

record有點像C/C++裏面的結構體。其實是語法糖,方便咱們的開發。代碼彙編時轉成tuple表達形式。app

Tupleide

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}


Recordpost

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處理atom

%% 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的彙編代碼spa

-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結構。
一、添加tuple元素
erlang:append_element(Tuple1, Term)
> erlang:append_element({one, two}, three).
{one,two,three}

等效於 list_to_tuple(tuple_to_list(Tuple1) ++ [Term]),但性能比後者高 


二、移除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

相關文章
相關標籤/搜索