Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I turn a list of tuple pairs into a record in Erlang?

Tags:

erlang

Let's say I have this:

-record(my_record, {foo, bar, baz}).

Keyvalpairs = [{foo, val1},
               {bar, val2},
               {baz, val3}].

Foorecord = #my_record{foo=val1, bar=val2, baz=val3}.

How do I convert Keyvalpairs into Foorecord?

like image 552
clofresh Avatar asked May 16 '09 23:05

clofresh


2 Answers

The simplest thing to do is:

Foorecord = #my_record{foo=proplists:get_value(foo, Keyvalpairs), 
      bar=proplists:get_value(bar, Keyvalpairs),
      baz=proplists:get_value(baz, Keyvalpairs)}.

If this is too repetitive you can do something like:

Foorecord = list_to_tuple([my_record|[proplists:get_value(X, Keyvalpairs)
      || X <- record_info(fields, my_record)]]).
like image 183
cthulahoops Avatar answered Oct 10 '22 18:10

cthulahoops


Like the other answers point out, you need to roll your own solution to accomplish this. The solutions proposed are however incomplete. For example, it doesn't take into account default values for record entries. I use the following code snippet to take care of this conversion:

%% @doc returns a "RECSPEC" that can be used by to_rec in order to 
%% perform conversions
-define(RECSPEC(R), {R, tuple_to_list(#R{}), record_info(fields, R)}).

%% @doc converts a property list into a record.
-spec to_rec(recspec(), proplist()) -> record().
to_rec({R, [_ | N], Spec}, P) when is_atom(R) and is_list(Spec) ->
    list_to_tuple(
      [R | lists:foldl(
         fun ({K,V}, A) ->
             case index_of(K, Spec) of
                 undefined -> 
                     A;
                 I -> 
                     {Head, Tail} = lists:split(I, A),
                      Rest = case Tail of
                                [_ | M] -> M;
                                []      -> []
                            end,
                     Head ++ [V | Rest]
             end
         end, N, P)]).

Now one can simply do:

-record(frob, {foo, bar="bar", baz}).

to_rec(?RECSPEC(frob), [{baz, "baz"}, {foo, "foo"}])

which yields

#frob{foo="foo", bar="bar", baz="baz"}

I put this into a little "toolbox" library I am building to collect these little "snippets" that just make life easier when developing Erlang applications: ETBX

like image 45
erick Avatar answered Oct 10 '22 18:10

erick