2008-09-15 67 views
3

我正在尝试重构一些代码,这些代码是用于收集呼叫队列中代理程序当前状态的软件。目前,对于我收听的6个事件中的每一个,我检查Mnesia表是否存在代理,并根据事件更改行中的某些值,或者如果代理不存在,则将其添加为新的值。目前我在每个事件中都有这个Mnesia事务,当然这是一堆重复的代码来检查代理的存在等等。合并Mnesia的记录

我想改变它,以便有一个函数,如change_agent/2,我从处理这个事件的事件中调用我。

我的问题当然是记录....我发现没有办法动态创建它们或合并其中的两个在一起或任何东西。最好有一个功能,我可以这样称呼:

change_agent("001", #agent(id = "001", name = "Steve")). 
change_agent("001", #agent(id = "001", paused = 0, talking_to = "None")). 

回答

2

我写了一些代码前一阵子是合并两个记录也不完全是动态的,但蒙山宏,你可以很容易地使用它的几个记录

它的工作原理是这样的:。合并/ 2函数接受两条记录并将它们与空记录一起转换为列表以供参考(记录类型在编译时定义,并且必须是。这是“非动态”部分)。然后这些记录通过通用函数merge/4运行如果定义了列表并从A中获取元素,否则从B中获取元素(如果已定义)或最后从Default(始终定义)中获取元素。

下面是代码(请原谅StackOverflow的糟糕的Erlang语法突出显示):

%%%---------------------------------------------------------------------------- 
%%% @spec merge(RecordA, RecordB) -> #my_record{} 
%%%  RecordA = #my_record{} 
%%%  RecordB = #my_record{} 
%%% 
%%% @doc Merges two #my_record{} instances. The first takes precedence. 
%%% @end 
%%%---------------------------------------------------------------------------- 
merge(RecordA, RecordB) when is_record(RecordA, my_record), 
          is_record(RecordB, my_record) -> 
    list_to_tuple(
     lists:append([my_record], 
        merge(tl(tuple_to_list(RecordA)), 
          tl(tuple_to_list(RecordB)), 
          tl(tuple_to_list(#my_record{})), 
          []))). 

%%%---------------------------------------------------------------------------- 
%%% @spec merge(A, B, Default, []) -> [term()] 
%%%  A = [term()] 
%%%  B = [term()] 
%%%  Default = [term()] 
%%% 
%%% @doc Merges the lists `A' and `B' into to a new list taking 
%%% default values from `Default'. 
%%% 
%%% Each element of `A' and `B' are compared against the elements in 
%%% `Default'. If they match the default, the default is used. If one 
%%% of them differs from the other and the default value, that element is 
%%% chosen. If both differs, the element from `A' is chosen. 
%%% @end 
%%%---------------------------------------------------------------------------- 
merge([D|ATail], [D|BTail], [D|DTail], To) -> 
    merge(ATail, BTail, DTail, [D|To]); % If default, take from D 
merge([D|ATail], [B|BTail], [D|DTail], To) -> 
    merge(ATail, BTail, DTail, [B|To]); % If only A default, take from B 
merge([A|ATail], [_|BTail], [_|DTail], To) -> 
    merge(ATail, BTail, DTail, [A|To]); % Otherwise take from A 
merge([],  [],  [],  To) -> 
    lists:reverse(To). 

随时以任何您想要的方式使用它。

3

很难为记录编写通用访问函数。 对此的一种解决方法是'exprecs'库,其中 将生成低级别记录访问函数的代码。

你需要做的事情是以下行添加到 模块:

-compile({parse_transform, exprecs}). 
-export_records([...]). % name the records that you want to 'export' 

的访问函数的命名约定可能看起来很奇怪,但被理查德·奥基夫的建议启发。它至少是一致的,不太可能与现有的功能发生冲突。 (:

+0

快速查看这可能不是我正在寻找的。不过很有意思,我会稍后再看看。 – 2008-09-15 16:33:59