具有不同记录中的通用名称的字段

时间:2015-10-08 00:46:08

标签: erlang

我有一些类似字段的记录,如下:

-define(COMMON_FIELDS, common1, common2, common3).
-record(item1, a, b, c, ?COMMON_FIELDS).
-record(item2, x, y, z, ?COMMON_FIELDS).

但后来我需要为每条记录编写类似的代码:

Record#item1.common1,
Record#item1.common2,
Record#item1.common3

Record#item2.common1,
Record#item2.common2,
Record#item2.common3

是否可以编写一个函数来访问不同记录中的相同字段?

3 个答案:

答案 0 :(得分:0)

  

是否可以编写一个函数来访问相同的字段   不同的记录?

1)多个函数子句中的模式匹配:

-module(x1).
-export([read/1]).
-define(COMMON_FIELDS, common1, common2, common3).

-record(item1, {x, ?COMMON_FIELDS}).  %Note that you defined your records incorrectly.
-record(item2, {y, ?COMMON_FIELDS}).

read(#item1{common1=C1, common2=C2, common3=C3} = _Item) ->
    io:format("~p, ~p, ~p~n", [C1, C2, C3]);
read(#item2{common1=C1, common2=C2, common3=C3} = _Item) ->
    io:format("~p, ~p, ~p~n", [C1, C2, C3]).

...

25> c(x1).
{ok,x1}
26> rr(x1).
[item1,item2]

27> A = #item1{x=10, common1="hello", common2="world", common3="goodbye"}.
#item1{x = 10,common1 = "hello",common2 = "world",
       common3 = "goodbye"}

28> B = #item2{y=20, common1="goodbye", common2="mars", common3="hello"}.  
#item2{y = 20,common1 = "goodbye",common2 = "mars",
       common3 = "hello"}

29> x1:read(A).                                                            
"hello", "world", "goodbye"
ok

30> x1:read(B).                                                            
"goodbye", "mars", "hello"
ok

注意导出语句 - 它是长度为1的列表,即模块导出一个函数。输出显示read()函数可以读取任何一种类型的记录。

2)案例陈述
如果出于某种原因,通过声明一个函数表示一个函数子句,您可以这样做:

read(Item) ->
    case Item of
        #item1{common1=C1, common2=C2, common3=C3} -> true;
        #item2{common1=C1, common2=C2, common3=C3} -> true
    end,

    io:format("~p, ~p, ~p~n", [C1, C2, C3]).

答案 1 :(得分:0)

您可以使用parse_transe中的exprecs解析变换。

-module(parse).
-compile({parse_transform, exprecs}).

-record(item1, {x, common1, common2}).
-record(item2, {y, common1, common2}).

-export_records([item1, item2]).

-export([p/0]).

f() ->
    R1 = #item1{x=1, common1=foo1, common2=bar1},
    R2 = #item2{y=2, common1=foo2, common2=bar2},

    ['#get-'(Field, Rec) || Field <- [common1, common2], Rec <- [R1, R2]].

...

1> c(parse).
{ok,parse}
2> parse:f().
[foo1,foo2,bar1,bar2]

答案 2 :(得分:0)

将公共字段分解为每个记录公司中的单个字段可能是有意义的,这些记录公司包含具有所有公共数据或甚至是数据的记录。然后重构代码,对其自己的函数进行所有常见处理。

您仍需要对每个顶级记录进行模式匹配以获取公共子记录。但是在某个地方你可能想要对每种记录类型进行特定的处理,你可以在那里匹配公共字段。

-record(common, {c1, c2, c3}).
-record(item1, {a, b, c, com}).
...

process_item(#item1{a=A, b=B, c=C, com=Com}) ->
     process_abc(A, B, C),
     process_common(Com),
     ...;
process_item(#item2{x=X, y=Y ...

这样的数据结构也可能表示使用新的Map数据类型而不是记录。