Pergunta

Estou tentando refatorar algum código que possuo para um software que coleta o status atual dos agentes em uma fila de chamadas.Atualmente, para cada um dos cerca de 6 eventos que ouço, verifico em uma tabela Mnesia se existe um agente e altero alguns valores na linha dependendo do evento ou adiciono-o como novo se o agente não existir.Atualmente tenho essa transação Mnesia em cada evento e claro que é um monte de códigos repetidos para verificar a existência de agentes e assim por diante.

Estou tentando alterá-lo para que haja uma função como agente_de_mudança/2 que eu chamo dos eventos que tratam disso para mim.

Meus problemas são, claro, registros....Não encontro nenhuma maneira de criá-los dinamicamente ou mesclar dois deles ou algo assim.De preferência, haveria uma função que eu poderia chamar como:

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

Solução

Escrevi um código há algum tempo que mescla dois registros.Não é totalmente dinâmico, mas com macros você pode usá-lo facilmente para vários registros.

Funciona assim:A função merge/2 pega dois registros e os converte em listas junto com o registro vazio para referência (o tipo de registro é definido em tempo de compilação e deve ser.Esta é a parte "não dinâmica").Estes são então executados através da função genérica merge/4 que trabalha com listas e pega elementos de A se estiverem definidos, caso contrário, de B se estiverem definidos, ou por último de Default (que é sempre definido).

Aqui está o código (desculpe o fraco destaque de sintaxe Erlang do StackOverflow):

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

Sinta-se à vontade para usá-lo da maneira que desejar.

Outras dicas

É difícil escrever funções genéricas de acesso para registros.Uma solução alternativa para isso é o 'expressos' Biblioteca, que gerará código para funções de acesso a registros de baixo nível.

O que você precisa fazer é adicionar as seguintes linhas a um módulo:

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

A convenção de nomenclatura para as funções de acesso pode parecer estranha, mas foi inspirada em uma proposta de Richard O'Keefe.É, pelo menos, consistente e pouco provável que entre em conflito com as funções existentes.(:

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top