S
S
Shizz2011-07-18 13:20:30
Erlang
Shizz, 2011-07-18 13:20:30

General pattern for working with records (erlang)?

Introduction: the module receives data in the form of a list
Input = [{c,CValue},{a,AValue},{b,BValue}]
The task is to shove the data into the #rec record, in accordance with the record description. If in erlang work with records was carried out at runtime, the function would be something like this:

-record(rec, {a,b,c}).<br/>
<br/>
build_rec_dynamic(Input) -&gt;<br/>
 Fields = record_info(fields, rec),<br/>
 build_payload(Input, Fields, #rec{}).<br/>
<br/>
build_rec_dynamic(Input, [Field|Fields], Result) -&gt;<br/>
 case lists:keyfind(Field, 1, Input) of<br/>
 {Field, Value} -&gt;<br/>
 build_payload(Input, Fields, Result#rec{Field = Value});<br/>
 false -&gt;<br/>
 {error, {undefined_field, Field}}<br/>
 end;<br/>
<br/>
build_rec_dynamic(Input, [], Result) -&gt;<br/>
 Result.

Due to the peculiarities of working with records, such a trick, of course, will not work:
field 'Field' is not an atom or _ in record rec
Is there any general pattern for processing dynamic data and presenting it in a record? I’ll note right away that the data may come in the wrong order, so just shoving everything into a tuple will not work, and you only need to pull out the necessary fields.

Answer the question

In order to leave comments, you need to log in

3 answer(s)
M
Maxim Sokhatsky, 2013-11-24
@5HT

Here is a parse transform that turns proplists into records and back.
https://github.com/5HT/n2o/blob/master/src/n2o_rest.erl
In the context of the task in relation to JSON transformations.
Here is an example of usage:
https://github.com/synrc/n2o_sample/blob/master/src/users.erl
You just write
AND for record #user{} automatically generate transformation functions to proplists and back (from_json and to_json).
If parse_transform doesn't suit you for some reason.
Here is the minimal code for educational purposes (map and unmap):

hunmap([],O,_,_) -> O;
hunmap([{BK,V}|T],O,Keys,0) -> O;
hunmap([{BK,V}|T],O,Keys,L) ->
    K = wf:to_atom(BK),
    hunmap(T, setelement(
         wf_utils:indexof(K,Keys),O,wf:to_list(V)), Keys--[K],L-1).

-define(unmap(Record), unmap(P,R) -> 
                     hunmap(P,R,record_info(fields, Record),size(R)-1)).
-define(map(Record), map(O) ->
    Y = [ try N=lists:nth(1,B), if is_number(N) -> 
            wf:to_binary(B); true -> B end catch _:_ -> B end
          || B <- tl(tuple_to_list(O)) ],
    lists:zip(record_info(fields, Record), Y)).

S
Shizz, 2011-07-18
@Shizz

Found a hack from Ulf Viger: forum.trapexit.org/viewtopic.php?p=21790#21790
Alternatively, you can use this module.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question