2008-09-15 85 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