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). 3record_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.
改動tuple結構
R16之後。erlang提供了2個接口用於改動tuple結構。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模塊彙編碼就可以找到答案了。
參考:http://blog.csdn.net/mycwq/article/details/31421341