2008-09-15 4 views
3

J'essaie de refactoriser du code que j'ai pour un logiciel qui recueille l'état actuel des agents dans une file d'attente d'appels. Actuellement, pour chacun des 6 événements que j'écoute, je vérifie dans une table Mnesia si un agent existe et change certaines valeurs dans la ligne en fonction de l'événement ou l'ajoute comme nouveau si l'agent n'existe pas. Actuellement, j'ai cette transaction Mnesia dans chaque événement et bien sûr c'est un tas de code répété pour vérifier l'existence d'agents et ainsi de suite.Fusion des enregistrements pour Mnesia

J'essaye de le changer de sorte qu'il y ait une fonction comme change_agent/2 que j'appelle des événements qui manipule ceci pour moi.

Mes problèmes sont bien sûr des enregistrements .... Je ne trouve aucun moyen de les créer dynamiquement ou de fusionner 2 d'entre eux ou quoi que ce soit. De préférence, il y aurait une fonction que je pourrais appeler comme:

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

Répondre

2

j'ai écrit un code il y a un moment qui fusionne deux enregistrements est pas tout à fait dynamique, mais cinque macros vous pouvez facilement l'utiliser pour plusieurs enregistrements

Il fonctionne comme ceci:.. La fonction de fusion/2 prend deux enregistrements et les convertit en listes avec l'enregistrement vide à titre de référence (le type d'enregistrement est défini au moment de la compilation, et doit être.) Il s'agit de la partie "non dynamique". avec des listes et prend des éléments de A si elles sont définies, sinon de B si elles sont définies, ou enfin de Default (qui est toujours défini)

Voici le code (excusez le pauvre Erlang de StackOverflow coloration syntaxique):

%%%---------------------------------------------------------------------------- 
%%% @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). 

N'hésitez pas à l'utiliser comme bon vous semble.

3

Il est difficile d'écrire des fonctions d'accès génériques pour les enregistrements. Une solution de contournement pour cela est la bibliothèque 'exprecs', qui va générer du code pour les fonctions d'accès aux enregistrements de bas niveau.

La chose que vous devez faire est d'ajouter les lignes suivantes à un module:

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

La convention de nommage pour les fonctions d'accès peut sembler étrange, mais a été inspiré par une proposition de Richard O'Keefe . Il est, au moins, cohérent et peu susceptible d'entrer en conflit avec les fonctions existantes. (:

+0

Un coup d'œil rapide sur ce n'est peut-être pas exactement ce que je cherchais. Mais intéressant néanmoins et quelque chose que je vérifierai plus tard. –

Questions connexes