[Erlang 0006] Erlang中的record与宏
在Erlang中使用Tuple ,数据项的顺序\数量都是确定的,
同时一些常量如果硬编码到代码中,一旦数值变化,
这两种数据层面的变化,在Erlang中对应的解决方案是: record Macro
在代码中我们创建一个record: -record(man , { name , age=0, school}).
我们通过下面的代码看看对应字段的默认值:
%See default value
M=#man{},
io:format("M is : ~p ~n", [ M ]),
可以看到输出M的值是:{man,undefined,0,
从纯数据的角度我们发现{man,undefined,0,
我们给特定的字段赋值,再看:
输出是 M2 is : {man,"zen",23,"No.14"}
以M2数据为模板,可以生成新的record:
结果是: M3 is : {man,"tt",24,"No.14"}
也可以这样使用数据模板:
下面的例子演示如何取值:
结果是: M4 is : {man,"tt2",24,undefined}
我们尝试嵌套一个record到man,
-record(name ,{firstname,lastname}).
我们使用M2作为数据模板来生成M5,
io:format("M5 firstname is : ~p ~n ", [ M5#man.name#name.firstname ])
在Erlang中匹配无处不在,
比如这个方法:
show2(#man{name =Name ,age =Age } = M ) when is_record(M , man) ->
io:format("Name : ~p Age: ~p ~n ", [ Name ,Age ]).
这个方法在入口的位置就提取出来了Name和Age,
上面是关于record的一些常规操作,我会有一些疑问:
同样的is_record 是怎么判断的?要想知道这个答案就需要重新编译我们的测试文件,
c(test,['E']).
io:format("M3 is : ~p ~n ", [ M3 ]),这句为例,编译出来的代码是:
再看看刚刚那段生成 show2生成的对应代码:
这里有一个匹配取值的,会影响我们阅读,我们简化一下:
它编译出来的代码是:
show({man,_,_,_} = M) when true ->
io:format("show M : ~p ~n ", [M]).
很难想象如果没有宏,我们的Erlang代码要多么的难读,
- 常量宏 比如-define(TIMEOUT, 1000). -define(ServerName,my_
first_game_server ).
- 带参宏 比如: -define(Eq(X,Y),X=:=Y).
-define(P(Content),ok). - 条件宏
-ifdef(product).
-define(Who,"product_db_adm").
-else.
-define(Who,"test_db_adm").
-endif. - 全局宏: ?MACHINE (VM 名称)
?LINE 当前代码行
?FILE 当前代码文件
还有最熟悉的?MODULE 当前模块
还有一个比较常用在输出调试信息的宏:
-define(VALUE(Call),io:format("~p = ~p~n",[??Call,Call])).
test1() -> ?VALUE(length([1,2,3])).
条件宏可以通过编译选项的方式,
按照同样的方法我们可以看一下Macro,只需要把编译的时候使用c(test,['P']).下面就是一个使用宏的例子,猜猜它被编译之后是什么样子?

-module(mac).
-export([dump/1,go/1,show/2,len/1,say/0]).
-define(Func,X).
-define(Double,*2).
-define(F,dump(X)).
-define(Eq(X,Y),X=:=Y).
%-define(P(Content),ok).
-define(PF(Content,Args),io:format(Content,Args)).
-define(P(Content),io:format(Content)).
-define(Len(Call),io:format("~p=~p ~n",[??Call,Call])).
-ifdef(me).
-define(Who,"abcd").
-else.
-define(Who,"zen").
-endif.
say()->
?P(?Who).
len(List) when is_list(List) ->
?Len(length(List)).
dump(X)->
?Func?Double.
go(X)->
?F.
show(X,Y) when ?Eq(X,Y)->
?P("They are Equal. ~n");
show(_X,_Y)->
io:format("HAHA").
生成的P文件在这里:

-file("./mac.erl", 1).
-module(mac).
-export([dump/1,go/1,show/2,len/1,say/0]).
say() ->
io:format("zen").
len(List) when is_list(List) ->
io:format("~p=~p ~n", ["length ( List )",length(List)]).
dump(X) ->
X * 2.
go(X) ->
dump(X).
show(X, Y) when X =:= Y ->
io:format("They are Equal. ~n");
show(_X, _Y) ->
io:format("HAHA").
在项目中,这些record macro 往往被放在hrl文件中,通过Emakefile进行编译定制,这个之前我们讨论过不再赘述,点击这里查看;